home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 001a / mskrmsrc.zip / MSGIBM.ASM next >
Assembly Source File  |  1991-10-24  |  168KB  |  5,157 lines

  1.      Name msgibm
  2. ; File MSGIBM.ASM
  3.     include mssdef.h
  4. ;       Copyright (C) 1982,1991, Trustees of Columbia University in the
  5. ;       City of New York.  Permission is granted to any individual or
  6. ;       institution to use, copy, or redistribute this software as long as
  7. ;       it is not sold for profit and this copyright notice is retained.
  8. ; Tektronix emulator for use with MS Kermit/IBM.
  9. ; Edit history:
  10. ; 6 Sept 1991 version 3.11
  11. ; 2 March 1991 version 3.10
  12. ; Last edit 5 March 1991
  13. ; 12 Nov 1990 Add text cursor symbol, and on 17 Nov add cursor on/off.
  14. ; 2 Nov 1990 Add Microsoft mouse direct support.
  15. ; 8 June 1989 Added Wyse-700 support from Mikko Laanti.
  16. ; 21 Nov 1988 Version 2.32
  17. ; 1 Nov 1987 Heavy rewrite to integrate code into regular MS Kermit/IBM
  18. ;  material. [jrd]
  19. ;==============================================================================
  20. ; Original version for TI Pro computers by
  21. ; 12-Dec-84  Joe Smith, CSM Computing Center, Golden CO 80401
  22. ; adapted to IBM PC June 1987 by    Brian Holley,
  23. ;                    Faculty of Economics and Politics
  24. ;                    University of Cambridge, England
  25. ;                    Email: BJH6@UK.AC.CAM.PHX
  26. ; Upgraded and integrated into MS Kermit 2.30 by Joe Doupnik, Utah State Univ.
  27. ;
  28. ;           Description of Tektronix commands
  29. ;
  30. ; ESC CONTROL-E (ENQ) requests a status report
  31. ; ESC FORMFEED erases the screen.
  32. ; ESC CONTROL-X turns on bypass mode (ignore incoming characters).
  33. ; ESC CONTROL-Z turns on the crosshairs (not on 4006 or 4025)
  34. ; ESC 2  exit Tek submode for text mode (ignore if doing full Tek)
  35. ; ESC ? is replaced by DEL code, to assist line plots with 7 bit systems.
  36. ; ESC [ Pn ; Pn m  set screen colors. Pn = 30 + sum of colors for foregnd,
  37. ;  40 + sum of colors for background, Pn = 0 sets b/w, Pn = 1 for high
  38. ;  intensity. Colors are red = 1, green = 2, blue = 4.
  39. ; ESC [ ? 3 8 l  exits Tek mode and returns to host text terminal type
  40. ;  (VT102 if none defined yet). This is an extension from DEC VT340's.
  41. ; ESC [ ? 256 n  invokes a screen size report, for Word Perfect. Report is
  42. ;   ESC [ ? 256; height; width; num colors n   where num colors is 0, 1 or
  43. ;   16; report ESC [ ? 24; 80; 0 n  for pure text mono systems.
  44. ; ESC @  through  ESC M  sets default fill pattern as below (1=@...).
  45. ; ESC Z  report terminal type (as VT320)
  46. ; ESC [ 2; 2 $ u  host request color palette report.
  47. ; ESC / xhome;yhome;xwidth;yheight x           draw an empty rectangle
  48. ; ESC / xhome;yhome;xwidth;yheight;pattern y   fill rectangle with pattern
  49. ; ESC / xhome;yhome;xwidth;yheight;pattern z   fill rect with pattern+border
  50. ;  where x/yhome is the lower left Tek corner, xwidth and yheight are the
  51. ;  Tek width and height. All values are decimal numbers.
  52. ;  Patterns 0:use default, 1:solid, 2:grey, 3:left to right slant, 4:right to
  53. ;  left slant, 5:horizontal lines, 6:vertical lines, 7:slanted cross-hatch,
  54. ;  8:vertical cross-hatch, 9:checkerboard; 10:dotted, 11:horiz herringbone,
  55. ;  12:vertical herringbone,13 and above:border without fill. All are tiling
  56. ;  8x8 pixel patterns.
  57. ; ESC / param a, ... ESC / param c  set user definable line drawing pattern
  58. ;  to 16 bit value of param; plot as lsb first.
  59. ; ESC / 2 h or l,  ESC / 9 h or l. h is set, l is reset, 2 is destructive
  60. ;  space and 9 is destructive backspace. Defaults are reset.
  61. ; ESC x  ESC y  ESC z   selects one of these user definable patterns above.
  62. ; ESC P  P1; P2; P3 q string ESC \        a Sixel Graphics command
  63. ;   P1 and P3 ignored, P2 = 0 or 2 means draw 0 bits in background, 1 means
  64. ;    skip them.
  65. ;   string is
  66. ;     sixel chars (3fh..7eh, lower 6 bits+3fh, displayed lsb at the top)
  67. ;     ! Pn sixel char        where Pn is a repeat count
  68. ;     " Pan; Pad; Ph; Pv    raster attributes (all ignored for now)
  69. ;     # Pc; Pu; Px; Py; Pz  coloring as follows
  70. ;    Pc is color palette, 0-255  (note, only 0..15 are predefined)
  71. ;    Pu is color units, 1=HLS, 2=RGB
  72. ;    For Hue Lightness Saturation:
  73. ;        Px = Hue angle, 0-360 degrees. The colors are mapped around
  74. ;        the color wheel in 60 degree segments as Hues:
  75. ;        0-29 deg = blue, 30-89 = magenta (blue + red), 90-149 = red,
  76. ;        150-209 = yellow (red + green), 210-269 = green,
  77. ;        270-329 = cyan (green + blue), 330-359 = blue.
  78. ;        Py = Lightness, 0-100%, Pz = Saturation, 0-100%
  79. ;          Lightness    Sat = 51-100    Sat = 11-50     Sat = 0-10
  80. ;          86-100    bold white    bold white     bold white
  81. ;          71-85        bold hue    bold white     bold white
  82. ;          57-70        bold hue    grey (dim white) grey
  83. ;          43-56        bold hue    dim hue         black
  84. ;          29-42        dim hue        grey         grey
  85. ;          14-28        dim hue        black         black
  86. ;           0-13     black        black         black
  87. ;        Note that Py = Pz = 50 gives the widest spectrum.
  88. ;    For RGB: Px = red, 0-100%, Py = green, 0-100%, Pz = blue, 0-100%
  89. ;        If any color exceeds 50% then the bold bit is turned on for
  90. ;        the ensemble (IBM ega display adapter constraint for RGBi).
  91. ;
  92. ;    Palette registers can be selected by the substring
  93. ;        # Pc    followed by a non-numeric char other than ";"
  94. ;            and Pc is the palette register, 0-255.
  95. ;
  96. ;     $  (dollar sign )     meaning go to left margin
  97. ;     -  (minus)         meaning go to left margin 6 dots down.
  98. ;   This command yields one or more sets of 6 vertically arranged dots. They
  99. ;   are placed starting at the top and left side of the current text cell.
  100. ;   Escape sequences are permitted within string and occur without disruption.
  101. ; CONTROL-] (GS) turns on plot mode, the first move will be with beam off.
  102. ; CONTROL-^ (RS) turns on incremental plot mode. RS space means move pen up
  103. ;  RS P means move pen down, following letters: A, E, D, F, B, J, H, I mean
  104. ;  move right, right and up, up, left and up, left, left and down, down, and
  105. ;  right and down, respectively. Ex: RS <space> J J J  means move three Tek
  106. ;  positions left and down with the pen up (invisibly).
  107. ; CONTROL-UNDERLINE (US) turns off plot mode, as does CR (for all but 4025).
  108. ; CONTROL-X switches from TEKTRONIX sub mode to NORMAL alpha mode but is
  109. ;  ignored if we are emulating a full Tek terminal rather than a sub mode
  110. ;  of DEC or Heath.
  111. ; FF erases screen.
  112. ; ESC letter, where letter is accent grave (`) a..e, sets the line drawing
  113. ;   pattern until reset to solid lines (same as escape accent) by command or
  114. ;   a terminal reset.
  115. ;    ENQ = Control E
  116. ;    ESC = Control [ (left square bracket)
  117. ;    FF = Control L
  118. ;    FS = Control \ (backslash)
  119. ;    GS = Control ] (right square bracket)
  120. ;    RS = Control ^ (caret)
  121. ;    US = Control _ (underscore)
  122. ;
  123. ; The plot commands are characters which specify the absolute position to move
  124. ; the beam.  All moves except the one immediately after the GS character
  125. ; (Control-]) are with a visible trace.
  126. ;
  127. ; For 4010-like devices - The positions are from 0 to 1023 for both X and Y,
  128. ; although only 0 to 780 are visible for Y due to screen geometry.  The screen
  129. ; is 10.23 by 7.80 inches, and coordinates are sent as 1 to 4 characters.
  130. ;
  131. ; For 4014-like devices - The positions are from 0 to 4096, but each movement
  132. ; is a multiple of 4 positions unless the high-resolution LSBXY are sent.  This
  133. ; makes it compatible with the 4010 in that a full sized plot fills the screen.
  134. ;
  135. ; HIX,HIY = High-order 5 bits of position
  136. ; LOX,LOY = Middle-order 5 bits of position
  137. ; LSBXY      = Low-order 2 bits of X + low-order 2 bits of Y (4014 mode)
  138. ;
  139. ; Hi Y      Lo Y      Hi X      LSBXY      Characters sent (Lo-X always sent)
  140. ; ----      ----      ----      -----      ----------------------------------
  141. ; Same      Same      Same      Same                 Lo-X
  142. ; Same      Same      Same      Diff        LSB, Lo-Y,     Lo-X    4014
  143. ; Same      Same      Diff      Same             Lo-Y, Hi-X, Lo-X
  144. ; Same      Same      Diff      Diff        LSB, Lo-Y, Hi-X, Lo-X    4014
  145. ; Same      Diff      Same      Same             Lo-Y,     Lo-X
  146. ; Same      Diff      Same      Diff        LSB, Lo-Y,     Lo-X    4014
  147. ; Same      Diff      Diff      Same             Lo-Y, Hi-X, Lo-X
  148. ; Same      Diff      Diff      Diff        LSB, Lo-Y, Hi-X, Lo-X    4014
  149. ; Diff      Same      Same      Same      Hi-Y,             Lo-X
  150. ; Diff      Same      Same      Diff      Hi-Y, LSB, Lo-Y,     Lo-X    4014
  151. ; Diff      Same      Diff      Same      Hi-Y,         Lo-Y, Hi-X, Lo-X
  152. ; Diff      Same      Diff      Diff      Hi-Y, LSB, Lo-Y, Hi-X, Lo-X    4014
  153. ; Diff      Diff      Same      Same      Hi-Y,         Lo-Y,     Lo-X
  154. ; Diff      Diff      Same      Diff      Hi-Y, LSB, Lo-Y,     Lo-X    4014
  155. ; Diff      Diff      Diff      Same      Hi-y,         Lo-Y, Hi-X, Lo-X
  156. ; Diff      Diff      Diff      Diff      Hi-y, LSB, Lo-Y, Hi-X, Lo-X    4014
  157. ; Offset for byte:          20h    60h  60h   20h     40h
  158. ;
  159. ; Note that LO-Y must be sent if HI-X has changed so that the TEKTRONIX knows
  160. ; the HI-X byte (in the range of 20h-3fh) is HI-X and not HI-Y.     LO-Y must
  161. ; also be sent if LSBXY has changed, so that the 4010 will ignore LSBXY and
  162. ; accept LO-Y.    The LSBXY byte is 60h + MARGIN*10h + LSBY*4 + LSBX. (MARGIN=0)
  163. ;
  164. ;
  165. ;
  166. ; External variable tekflg and calls to tekini, tekemu, tekesc, tekcls:
  167. ; Byte TEKFLG is non-zero when the Tek emulator is active; it is set by the
  168. ; startup code in tekini and is maintained in this file. Internal variable
  169. ; inited remembers if we have a graphics screen saved, etc.
  170. ; TEKINI must be called when entering the emulator to establish the graphics
  171. ; screen mode and to calculate the screen dimensions.
  172. ; TEKRINT reinitialize complete emulator.
  173. ; TEKESC is called from say mszibm.asm to invoke Tek emulation when the
  174. ; external procedures have detected an Escape Control-L sequence. An implicit
  175. ; initialization is done if necessary.
  176. ; TEKEMU is the normal entry point to pass a received character to the emulator.
  177. ; It too will do an implicit initialization, if required.
  178. ; TEKCLS clears the graphics screen, but only if the emulator is active.
  179. ; The emulator remains active during Connect mode Help, Status, and other
  180. ; interrupts which do not change the terminal type.
  181.  
  182.      
  183.     public    tekemu,tekini,tekrint,tekend,tekgraf ; Terminal emulation
  184.         public    tekflg, tekdmp, tekinq, tekpal, tekrpal    ; used by mszibm file
  185.     public    chcontrol, tekcursor, tekgcptr        ; used by msyibm file
  186.  
  187. ENQ    equ    05h            ; ^E ENQ for TEK enquiries
  188. CAN    equ    18h            ; ^X to return to ANSI mode
  189. ESCZ    equ    1Ah            ; SUB, ESC-^Z triggers crosshairs
  190. VT    equ    0Bh            ; ^K go up one line
  191. FS    equ    1Ch            ; ^\ for point plot mode
  192. GS    equ    1Dh            ; ^] draw line (1st move is invisible)
  193. RS    equ    1Eh                   ; ^^ for incremental line plot mode
  194. US    equ    1Fh            ; ^_ (underscore) returns to text mode
  195. accent    equ    60h            ; accent grave
  196.  
  197. txtmode    equ    4            ; text mode for TEKTRONIX status
  198. maxtekx equ    1024            ; horizontal and
  199. maxteky equ    780            ; vertical resolution of TEK 4010
  200.      
  201. screen    equ    10h            ; IBM Bios screen call
  202.      
  203. uparr    equ    72            ; DOS scan codes for arrow keys
  204. dnarr    equ    80
  205. lftarr    equ    75
  206. rgtarr    equ    77
  207. homscn    equ    71            ; DOS home screen scan code
  208. shuparr    equ    '8'            ; ascii codes for shifted arrows
  209. shdnarr    equ    '2'
  210. shlftarr equ    '4'
  211. shrgtarr equ    '6'
  212. mouse    equ    33h            ; Microsoft mouse interrupt
  213. msread    equ    3            ; mouse, read status and position
  214. mswrite    equ    4            ; mouse, set position
  215. mshoriz    equ    7            ; mouse, set min/max horizontal motion
  216. msvert    equ    8            ; mouse, set min/max vertical motion
  217. msgetbf    equ    21            ; mouse, get state buffer size
  218. msgetst    equ    22            ; mouse, get mouse state to buffer
  219. mssetst    equ    23            ; mouse, set mouse state from buffer
  220. msreset    equ    33            ; mouse, software reset
  221.  
  222.                     ; Graph_mode for different systems:
  223. cga    equ    6            ; highest resolution mode for CGA
  224. mono    equ    7            ; real monochrome display adapter
  225. colorega equ    14            ; Low-res mode, color EGA
  226. monoega equ    15            ; mono ega needs mode 15
  227. ega    equ    16            ; Hi-res mode - EGA
  228. olivetti equ    72            ; Olivetti's Hi-res - 50 lines text
  229. toshiba    equ    74h            ; Toshiba T3100, like Olivetti
  230. vaxmate    equ    0D0h            ; DEC VAXmate II, like Olivetti
  231. wyse700 equ    0D3h            ; Wyse-700 1280 * 400
  232. hercules equ    255            ; pseudo mode for Hercules graphics
  233. ; Note: IBM VGA modes 17 & 18, 640 by 480, can be used by setting "ega" above
  234. ; to 17 or 18 and modifying ybot to be 479 and ymult to be 48 at label tekin5.
  235. ; The code will scale everything appropriately for the new screen size, but
  236. ; there will be insufficient memory to retain the entire graphics image.
  237. ; Manual override SET TERMINAL GRAPHICS VGA accomplishes these two steps.
  238. ;
  239. ; Note: WYSE-700 mode 1024 * 780 and 1280 * 800 can be set only by
  240. ; manual override SET TERMINAL GRAPHICS WYSET or WYSEA, respectively.
  241. ; No automatic sensing for Wyse.
  242.  
  243. segega    equ    0a000h            ; segments of display memory, EGA,VGA
  244. segcga    equ    0b800h            ; CGA, AT&T/Olivetti and relatives
  245. seghga    equ    0b000h            ; HGA
  246. segmono    equ    0b000h            ; Monochrome
  247. segwyse equ    0a000h            ; wyse-700, both banks start from here
  248.                     ; Wyse equates:
  249. wystoff equ    03ddh            ; set bank start offset
  250. wystseg equ    03deh            ; set bank start base
  251. wymode    equ    03dfh            ; register to select mode & bank
  252. wybeven equ    0c8h            ; mask for R/W even bank
  253. wybodd    equ    0cbh            ; mask for R/W odd bank
  254.  
  255.                     ; Hercules equates:
  256. index    equ    03b4h            ; 6845 index register
  257. cntrl    equ    03b8h            ; Display mode control port
  258. hstatus    equ    03bah            ; status port
  259. scrn_on equ    8            ; bit to turn screen on
  260. grph    equ    2            ; graphics mode
  261. text    equ    20h            ; text mode
  262. config    equ    03bfh            ; configuration port
  263. genable equ    1+2            ; enable graphics (1) on two pages (2) 
  264. rgbbold    equ    80            ; nor/bold threshold for RGB intensity
  265. hiy    equ    1            ; codes for Tek graphics components
  266. loy    equ    2
  267. hix    equ    4
  268. lox    equ    3
  269. ; maxparam and maxinter must agree with the prime equ's in file mszibm.asm
  270. maxparam equ    10            ; number of ESC and DCS Parameters
  271. maxinter equ    10            ; number of ESC and DCS Intermediates
  272.  
  273.                     ; Pixel basic operation codes
  274. pixor    equ    1            ; write as foreground OR current dot
  275. pixbak    equ    2            ; write as absolute background color
  276. pixxor    equ    4            ; write as foreground XOR current dot 
  277. pixfor    equ    8            ; write absolute foreground color
  278.  
  279. data    segment
  280.     extrn    flags:byte, portval:word, rxtable:byte, vtemu:byte     
  281.     extrn    tv_mode:byte, yflags:byte, low_rgt:byte
  282.     extrn    param:word, nparam:word, inter:byte, ninter:word, lparam:byte
  283.     extrn    parstate:word, pardone:word, parfail:word
  284.     extrn    dnparam:word, dparam:word, dlparam:byte, dninter:word
  285.     extrn    dinter:byte, dcsstrf:byte, emubufc:word, emubuf:byte
  286.     extrn    emubufl:word, ttyact:byte, vtclear:byte
  287.  
  288. ; required for Hercules screen handling
  289.      
  290. gtable    db    35h,2dh,2eh,7        ; bytes for 6845 controller
  291.     db    5bh,2,57h,57h        ; - graphics mode
  292.     db    2,3,0,0
  293.      
  294. ttable    db    61h,50h,52h,0fh        ; bytes for 6845 controller
  295.     db    19h,6,19h,19h        ; - text mode
  296.     db    2,0dh,0bh,0ch
  297.  
  298. attlogo    db    'OLIVETTI'        ; Olivetti M24/28, AT&T 6300 rom id
  299. attllen    equ    $-attlogo        ; length
  300. toshlogo db    '  TT33110000  TTOOSSHHIIBBAA' ; Toshiba T3100 logo
  301. toshlen    equ    $-toshlogo        ; length
  302. declogo    db    'Copyright Digital Equipment Corp' ; DEC VAXmate
  303. declen    equ    $-declogo
  304. dumpname db    'TEKPLT.TIF',0        ; dump name
  305. dumplen    equ    $-dumpname
  306. tempname db    84 dup (0)        ; temp work area
  307. dhandle    dw    -1            ; dump file handle
  308.  
  309. ttstate    dw    tektxt            ; state machine control pointer
  310. prestate dw    0            ; previous state, across interruptions
  311. visible db    0            ; 0 to move, 1 to draw a line
  312. tek_hiy dw    0            ; Y coordinate in Tektronix mode
  313. tek_loy db    0
  314. tek_hix dw    0            ; X coordinate in Tektronix mode
  315. tek_lox db    0
  316. tek_lsb db    0            ; Low-order 2 bits of X + low Y
  317.                     ;    (4014 mode)
  318. status    db    0
  319. lastc    db    0            ; last x/y coord fragment seen       
  320. bnkchan db    0            ; a flag so we can select which bank
  321.                     ; to write in Wyse 1280*800 mode
  322. colpal    db    0,9,0ch,0ah        ; VT340 color palette table, IRGB
  323.     db    0dh,0bh,0eh,7, 8,1,4,2, 5,3,6,0fh ; 16 bytes, active table
  324.     db    256-($-colpal) dup (0)    ; to make 256 entries overall
  325. coldef    db    0,9,0ch,0ah, 0dh,0bh,0eh,7, 8,1,4,2, 5,3,6,0fh ; color def
  326. mondef    db    0,7 dup (0fh), 8 dup (7) ; monochrome default "colors"
  327. havepal    db    0            ; 1 if have selected palette
  328. masktab db    80h,40h,20h,10h,8,4,2,1 ; quicker than calculations!
  329.                     ; dashed line patterns
  330. linetab    dw    0ffffh            ; ESC accent    11111111 11111111
  331.     dw    0aaaah            ; ESC a        10101010 10101010
  332.     dw    0f0f0h            ; ESC b        11110000 11110000
  333.     dw    0fafah            ; ESC c        11111010 11111010
  334.     dw    0ffcch            ; ESC d        11111111 11001100
  335.     dw    0fc92h            ; ESC e        11111100 10010010
  336.     dw    0ffffh            ; ESC x    user defined
  337.     dw    0ffffh            ; ESC y user defined
  338.     dw    0ffffh            ; ESC z user defined
  339. linepat    dw    0ffffh            ; active line pattern, from above
  340.  
  341. tekid    db    escape,'[?63;1;2;4;8;9;15c',0; VT320, level 3, etc
  342. ;End of init data
  343.  
  344.     even
  345. xmult    dw    1            ; scaling factor for x is
  346. xdiv    dw    1            ;     xmult/xdiv
  347. ymult    dw    1            ; scaling factor for y is
  348. ydiv    dw    1            ;     ymult/ydiv
  349. xmax    dw    1            ;
  350. ybot    dw    1            ;
  351. x_coord dw    0            ; Tek text char X coordinate
  352. y_coord dw    0            ; Tek text char Y coordinate
  353. xcursor    dw    0            ; PC x_coord of text cursor symbol
  354. ycursor    dw    0            ; PC y_coord of text cursor symbol
  355. xcross    dw    0            ; crosshair coordinates
  356. ycross    dw    0
  357. xcenter    dw    0            ; center of screen
  358. ycenter    dw    0            ; center of screen
  359. tekcursor db    1            ; show text cursor (non-zero)
  360. cursorst db    0            ; cursor state (non-zero is displayed)
  361. oldx    dw    0            ; Tek coordinates of last point
  362. oldy    dw    767            ;  initially top left
  363. scalex    dw    0            ; PC coord for scaled x value
  364. scaley    dw    0            ;  for scaled y value
  365. rectx1    dw    0            ; Rectangle PC x lower left corner
  366. recty1    dw    0            ; Rectangle PC y lower left corner
  367. rectx2    dw    0            ; Rectangle PC x width
  368. recty2    dw    0            ; Rectangle PC y height
  369. numlines dw    0            ; number of lines to fill
  370.                     ; area fill material
  371. fill    db    0            ; current fill byte pattern
  372. fillptr    dw    filpat1            ; pointer to current fill pattern
  373. fillist    dw    filpat1,filpat2,filpat3,filpat4,filpat5,filpat6,filpat7
  374.     dw    filpat8,filpat9,filpat10,filpat11,filpat12,filpat13
  375.     dw    filpat14
  376. numfil    equ    ($-fillist)/2        ; number of fill patterns
  377.     ; fill patterns, 8 bits wide, first byte is at top of PC screen
  378.     ; 8 bytes per pattern for 8 scan line repetition
  379. filpat1    db    8 dup (0ffh)        ; solid fill
  380. filpat2    db    4 dup (0aah, 55h)    ; grey (alternating dots)
  381. filpat3    db    80h,01h,02h,04h, 08h,10h,20h,40h ; right to left slant up
  382. filpat4    db    80h,40h,20h,10h, 08h,04h,02h,01h ; left to right slant up
  383. filpat5 db    2 dup (0,0,0aah,0)    ; horizontal lines
  384. filpat6    db    8 dup (44h)        ; vertical lines
  385. filpat7    db    80h,41h,22h,14h, 08h,14h,22h,41h   ; slanted crosshatch
  386. filpat8    db    2 dup (0aah,80h,80h,80h)  ; vertical crosshatch
  387. filpat9    db    4 dup (0f0h), 4 dup (0fh) ; checkerboard
  388. filpat10 db    4 dup (44h, 11h)    ; dots
  389. filpat11 db    2 dup (10h,28h,44h,82h)    ; horizontal herringbone
  390. filpat12 db    80h,40h,20h,10h,08h,10h,20h,40h ; vertical herringbone
  391. filpat13 db    8 dup (0ffh)        ; first user definable fill
  392. filpat14 db    8 dup (0ffh)        ; second user definable fill
  393.                     ; end of area fill material
  394. curmode    db    0            ; screen mode before graphics
  395. tekgraf    db    0        ; Tek graphics board selection (def=auto)
  396.                 ; local variables for LINE plotting routine
  397. graph_mode db    0            ; graphics video mode, default is none
  398. cursor    dw    0            ; saved text cursor
  399. inited    db    0            ; non-zero if inited (retains page)
  400. tekflg    db    0            ; Tek mode active flag
  401.                     ;  1=Tek reads serial port
  402.                     ;  2=VT300 emulator reads serial port
  403. tekident db    0            ; Tek ident request flag
  404. flow    dw    0            ; flow control word
  405. gpage    db    0            ; display adapter graphics page
  406. gfcol    db    15            ; graphics foreground colour
  407. gbcol    db    0            ; graphics background color
  408. tfcol    db    0            ; temp foreground color
  409. tbcol    db    0            ; temp background color
  410. colortb    db    0,4,2,6,1,5,3,7        ; color reversed-bit setting bytes
  411. ccode    db    pixfor            ; temp for holding plot color code
  412. bypass    db    0            ; GIN mode bypass condition (0=off)
  413. esctype    db    0            ; first char after ESCAPE char
  414. bscontrol db    0            ; non-zero for destructive BS
  415. spcontrol db    0            ; non-zero for destructive SPACE
  416. chcontrol db    0            ; char-writing, 1=opaque,0=transparent
  417.     even
  418. mousebuf dw    0            ; segment of mouse save buffer
  419. putc    dw    mputc            ; ptr to plot a character routine
  420. psetup    dw    psetupm            ; ptr to plot setup routine
  421. pincy    dw    pincym            ; ptr to inc y routine
  422. plotptr    dw    pltmon            ; ptr to dot plot routine
  423. gfplot    dw    bpltmon            ; ptr to area-fill plot routine
  424. segscn    dw    0b800h            ; actual screen segment to use
  425. doneptr    dw    offset xpardone,seg xpardone ; far pointer for tpardone use
  426. dumpptr    dw    offset dump,seg dump    ; far pointer for dump use
  427. initptr    dw    offset tekini,seg tekini
  428. rptptr    dw    offset tekrpt,seg tekrpt
  429. endptr    dw    offset tekend,seg tekend
  430. tekpptr dw    offset tekxco4,seg tekxco4
  431. linelen    dw    0            ; offset increment between scan lines
  432. ten    dw    10            ; word 10 for multiplying
  433. temp    dw    0
  434.  
  435. ; 8*8 font for Hercules and such, CGA, and EGA
  436. ; - allows 43 lines, and 80 (90 for Hercules) chars per line.
  437. ; all printing (?) characters from <space> to <del> - two characters per line
  438. ; 8 bits per scan line, top line given first, 8 scan lines.    
  439. font    db    0,0,0,0,0,0,0,0,           18h,18h,18h,18h,18h,0,18h,0
  440.     db    6ch,6ch,6ch,0,0,0,0,0,           36h,36h,7fh,36h,7fh,36h,36h,0
  441.     db    0ch,3fh,68h,3eh,0bh,7eh,18h,0, 60h,66h,0ch,18h,30h,66h,06h,0
  442.     db    38h,6ch,6ch,38h,6dh,66h,3bh,0, 0ch,18h,30h,0,0,0,0,0
  443.     db    0ch,18h,30h,30h,30h,18h,0ch,0, 30h,18h,0ch,0ch,0ch,18h,30h,0
  444.     db    0,18h,7eh,3ch,7eh,18h,0,0,     0,18h,18h,7eh,18h,18h,0,0
  445.     db    0,0,0,0,0,18h,18h,30h,           0,0,0,7eh,0,0,0,0
  446.     db    0,0,0,0,0,18h,18h,0,           0,06h,0ch,18h,30h,60h,0,0
  447.     db    3ch,66h,6eh,7eh,76h,66h,3ch,0, 18h,38h,18h,18h,18h,18h,7eh,0
  448.     db    3ch,66h,06h,0ch,18h,30h,7eh,0, 3ch,66h,06h,1ch,06h,66h,3ch,0
  449.     db    0ch,1ch,3ch,6ch,7eh,0ch,0ch,0, 7eh,60h,7ch,06h,06h,66h,3ch,0
  450.     db    1ch,30h,60h,7ch,66h,66h,3ch,0, 7eh,06h,0ch,18h,30h,30h,30h,0
  451.     db    3ch,66h,66h,3ch,66h,66h,3ch,0, 3ch,66h,66h,3eh,06h,0ch,38h,0
  452.     db    0,0,18h,18h,0,18h,18h,0,       0,0,18h,18h,0,18h,18h,30h
  453.     db    0ch,18h,30h,60h,30h,18h,0ch,   0,0,0,7eh,0,7eh,0,0,0
  454.     db    30h,18h,0ch,06h,0ch,18h,30h,   0,3ch,66h,0ch,18h,18h,0,18h,0
  455.     db    3ch,66h,6eh,6ah,6eh,60h,3ch,   0,3ch,66h,66h,7eh,66h,66h,66h,0
  456.     db    7ch,66h,66h,7ch,66h,66h,7ch,   0,3ch,66h,60h,60h,60h,66h,3ch,0
  457.     db    78h,6ch,66h,66h,66h,6ch,78h,   0,7eh,60h,60h,7ch,60h,60h,7eh,0
  458.     db    7eh,60h,60h,7ch,60h,60h,60h,   0,3ch,66h,60h,6eh,66h,66h,3ch,0
  459.     db    66h,66h,66h,7eh,66h,66h,66h,   0,7eh,18h,18h,18h,18h,18h,7eh,0
  460.     db    3eh,0ch,0ch,0ch,0ch,6ch,38h,   0,66h,6ch,78h,70h,78h,6ch,66h,0
  461.     db    60h,60h,60h,60h,60h,60h,7eh,   0,63h,77h,7fh,6bh,6bh,63h,63h,0
  462.     db    66h,66h,76h,7eh,6eh,66h,66h,   0,3ch,66h,66h,66h,66h,66h,3ch,0
  463.     db    7ch,66h,66h,7ch,60h,60h,60h,   0,3ch,66h,66h,66h,6ah,6ch,36h,0
  464.     db    7ch,66h,66h,7ch,6ch,66h,66h,   0,3ch,66h,60h,3ch,06h,66h,3ch,0
  465.     db    7eh,18h,18h,18h,18h,18h,18h,   0,66h,66h,66h,66h,66h,66h,3ch,0
  466.     db    66h,66h,66h,66h,66h,3ch,18h,   0,63h,63h,6bh,6bh,7fh,77h,63h,0
  467.     db    66h,66h,3ch,18h,3ch,66h,66h,   0,66h,66h,66h,3ch,18h,18h,18h,0
  468.     db    7eh,06h,0ch,18h,30h,60h,7eh,   0,7ch,60h,60h,60h,60h,60h,7ch,0
  469.     db    0,60h,30h,18h,0ch,06h,0,0,     3eh,06h,06h,06h,06h,06h,3eh,0
  470.     db    18h,3ch,66h,42h,0,0,0,0,       0,0,0,0,0,0,0,0ffh
  471.     db    30h,18h,0ch,0,0,0,0,0,           0,0,3ch,06h,3eh,66h,3eh,0
  472.     db    60h,60h,7ch,66h,66h,66h,7ch,0, 0,0,3ch,66h,60h,66h,3ch,0
  473.     db    06h,06h,3eh,66h,66h,66h,3eh,0, 0,0,3ch,66h,7eh,60h,3ch,0
  474.     db    0eh,18h,18h,3ch,18h,18h,18h,0, 0,0,3eh,66h,66h,3eh,06h,3ch
  475.     db    60h,60h,7ch,66h,66h,66h,66h,0, 18h,0,38h,18h,18h,18h,3ch,0
  476.     db    18h,0,38h,18h,18h,18h,18h,70h, 60h,60h,66h,6ch,78h,6ch,66h,0
  477.     db    38h,18h,18h,18h,18h,18h,3ch,0, 0,0,76h,7fh,6bh,6bh,63h,0
  478.     db    0,0,7ch,66h,66h,66h,66h,0,     0,0,3ch,66h,66h,66h,3ch,0
  479.     db    0,0,7ch,66h,66h,7ch,60h,60h,0, 0,3eh,66h,66h,3eh,06h,07h
  480.     db    0,0,6ch,76h,60h,60h,60h,0,     0,0,3eh,60h,3ch,06h,7ch,0
  481.     db    30h,30h,7ch,30h,30h,30h,1ch,0, 0,0,66h,66h,66h,66h,3eh,0
  482.     db    0,0,66h,66h,66h,3ch,18h,0,     0,0,63h,6bh,6bh,7fh,36h,0
  483.     db    0,0,66h,3ch,18h,3ch,66h,0,     0,0,66h,66h,66h,3eh,06h,3ch
  484.     db    0,0,7eh,0ch,18h,30h,7eh,0,     0ch,18h,18h,70h,18h,18h,0ch,0
  485.     db    18h,18h,18h,0,18h,18h,18h,0,   30h,18h,18h,0eh,18h,18h,30h,0
  486.     db    31h,6bh,46h,0,0,0,0,0,           0ffh,6 dup (81h),0ffh
  487.     ; note, the last 8 bytes comprise the text cursor symbol pattern
  488.  
  489. ; TIFF version 5.0 data fields
  490. ; Reference: Aldus/Microsoft Technical Memorandum dated 8/8/88
  491.                     ; TIFF data item size indicators
  492. uchar    equ    1            ; unsigned byte
  493. ascii    equ    2            ; asciiz string byte
  494. integer    equ    3            ; 16 bit unsigned integer
  495. long    equ    4            ; 32 bit unsigned integer
  496. rational equ    5            ; 32 bit numerator, 32 bit denominator
  497.  
  498. entry    struc                ; 12 byte image file directory entries
  499.     dw    ?            ; tag
  500.     dw    integer            ; type, of data item
  501. entcnt    dd    1            ; length, count of data items
  502. entval    dw    0            ; long value or long offset to value
  503.     dw    0
  504. entry    ends
  505.     
  506.     even                ; TIFF 5.0,  8 byte header
  507. header    dw    4949h            ; 'll', low byte stored first
  508.     dw    42            ; TIFF identification, 42 decimal
  509.     dw    nentry-header,0        ; long offset to image file directory
  510.                     ; Image File Directory
  511. nentry    dw    entrycnt        ; number of entries to follow
  512.                     ; 12-byte directory entries
  513. newsub    entry    <0feh,long>        ; new subfield type
  514. iwidth    entry    <100h,integer>        ; image width,  integer for WP 5
  515. ilength entry    <101h,integer>        ; image length, integer for WP 5
  516. bps    entry    <102h,,,4>         ; bits per sample, 4=iRGB, 1=B/W
  517. comp    entry    <103h,,,1>        ; compression, none
  518. photo     entry    <106h,,,3>        ; photometric interpret, palette 
  519. strip     entry    <111h,long,25,stripoff-header> ; offset to long strip offsets
  520. spp    entry    <115h,,,1>        ; samples/pixel, 1
  521. rps    entry    <116h,long,1,25>    ; long rows per strip
  522. sbc    entry    <117h,integer,25,stripbc-header> ; offset to strip byte counts
  523. xres    entry    <11ah,rational,1,xresval-header> ; x axis resolution
  524. yres    entry    <11bh,rational,1,yresval-header> ; y axis resolution
  525. resunit entry    <128h,integer,1,1>    ; resolution unit, no absolute units
  526. soft    entry    <131h,ascii,proglen,prog-header> ; software ident
  527. stamp    entry    <132h,ascii,dtlen,dandt-header>  ; date and time stamp
  528. cmap    entry    <140h,integer,3*16,colmap-header> ; palette color map
  529. entrycnt equ    ($-nentry-2+11)/12    ; compute number of entries for nentry
  530.     dd    0            ; long offset of next directory (none)
  531.                     ; supporting data pointed at above
  532. prog    db    'MS Kermit 300',0    ; originating program, asciiz
  533. proglen equ    $-prog
  534. dandt    db    '1989:12:25 00:00:01',0    ; date and time format
  535. dtlen    equ    $-dandt
  536. xresval dw    0,0,1,0            ; two double words (top / bottom)
  537. yresval dw    0,0,1,0            ; two double words (top / bottom)
  538. stripoff dd    25 dup (0)        ; long file offset for each strip
  539. stripbc dw    25 dup (0)        ; integer byte count for each strip
  540.     ; color map for red, green, blue; index by IRGB bits from ega sample
  541. colmap    dw    4 dup (0), 4 dup (007ffh), 4 dup (0), 4 dup (0ffffh) ; red
  542.     dw    2 dup (0,0,007ffh,007ffh), 2 dup (0,0,0ffffh,0ffffh) ; green
  543.     dw    2 dup (0,007ffh,0,007ffh), 2 dup (0,0ffffh,0,0ffffh) ; blue
  544. tifflen equ    $-header         ; length of header + directory + info
  545. pixdata equ    $              ; pixel data start here on disk
  546.                     ; end of TIFF information
  547.  
  548. esctab    db    34            ; table of ESC <char> dispatches
  549.     dw    escjmp            ; address of table for action routines
  550.     db    ENQ,FF,CAN,CTLZ,'/'            ; ^E,^L,^X,^Z,/
  551.     db    '2','@ABCD','EFGHI','JKLM'
  552.     db    3fh,'PZ[\'                ; '?PZ[\'
  553.     db    60h,'abcde','xyz'            ; accent, a..e,x,y,z
  554.  
  555. ; Dispatch for esctab table
  556.     even
  557. escjmp    dw    tekenq, tekcls,tekcan, tekgin,tekeseq    ; ^E,^L,^X,^Z,/
  558.     dw    tektwo,14 dup (tekfill)            ; '2@ABCDEFGHIJKLM'
  559.     dw    tekqury,tekeseq,sendid,tekeseq,tekgotst ; '?PZ[\'
  560.     dw    9 dup (teklpat)                ; accent, a..e,x,y,z
  561.  
  562. ; Final char table for ANSI escape sequences
  563. anstab    db    21            ; number of entries
  564.     dw    ansjmp            ; address of action routines
  565.     db    '@ABCD','EFGHJ','KXade','fhlmn','u'
  566.  
  567. ; Dispatch for anstab table
  568.     even
  569. ansjmp    dw    ansich, atcuu,   atcud,   atcuf,  atcub        ; '@ABCD'
  570.     dw    atcnl,  atcpl,   atcha,   atcup,  ated        ; 'EFGHJ'
  571.     dw    atel,   atech,   atcuf,   atcva,  atcud        ; 'KXade'
  572.     dw    atcup,  escexit, escexit, tekcol, tekrid    ; 'fhlmn'
  573.     dw    tekprpt                        ; 'u'
  574. data    ends
  575.  
  576. code    segment                    ; main body code segment
  577.     extrn    outchr:near, beep:near, scrseg:near, cmblnk:near
  578.     extrn    savescr:near, restscr:near, cptchr:near, clrbuf:near
  579.     extrn    iseof:near, atparse:near, unique:near
  580.     extrn    chgdsp:near, pcwait:near, vtrmac:near, vtsmac:near
  581.  
  582.     assume    cs:code, ds:data, es:nothing
  583.  
  584. ; These far routines are called by the Tek emulator; they are here to provide
  585. ; a bridge to the main code segment near procedures.
  586.      
  587. ; Procedures for calling to the main body of MS Kermit. Most are FAR and
  588. ; must be in in code segment named code, not in code2.
  589.  
  590. outmodem proc    far            ; send Tek char out serial port
  591.     push    ax
  592.     mov    ah,al
  593.     call    outchr            ; outchr reads from ah
  594.     pop    ax
  595.     ret
  596. outmodem ENDP
  597.  
  598. tekbeep    proc    far            ; sound a beep from Tek mode
  599.     call    beep
  600.     ret
  601. tekbeep    endp
  602.  
  603. tcmblnk    proc    far            ; blank the screen from Tek mode
  604.     call    cmblnk
  605.     ret
  606. tcmblnk    endp
  607.  
  608. tsavescr proc    far            ; save text screen while in Tek mode
  609.     call    savescr
  610.     ret
  611. tsavescr endp
  612.  
  613. trestscr proc    far            ;restore text screen while in Tek mode
  614.     cmp    low_rgt,80        ; were we in 80 column mode?
  615.     jbe    trestsc1        ; be = yes
  616.     mov    al,1            ; set to 132 columns
  617.     call    chgdsp            ; msyibm routine to change screen
  618. trestsc1:
  619.     call    restscr
  620.     ret
  621. trestscr endp
  622.  
  623. tscrseg    proc    far            ; get video segment while in Tek mode
  624.     call    scrseg
  625.     ret
  626. tscrseg    endp
  627.  
  628. tcptchr    proc    far            ; call session logger while in Tek
  629.     call    cptchr            ;  mode
  630.     ret
  631. tcptchr    endp
  632.  
  633. tiseof    proc    far            ; call iseof while in Tek mode
  634.     call    iseof
  635.     ret
  636. tiseof    endp
  637.  
  638. tparstart proc    far            ; start escape sequence parser
  639.     mov    parstate,0        ; set to initialize automatically
  640.     mov    pardone,offset tpardone    ; jmp to this when completed
  641.     mov    parfail,0        ; no failure case jump
  642.     ret
  643. tparstart endp
  644.  
  645. tparser    proc    far
  646.     call    atparse            ; reach to real parser
  647.     ret
  648. tparser    endp
  649.  
  650. tpardone proc    near            ; called by real parser
  651.     call    dword ptr doneptr    ; far call xpardone, old MASM way
  652.     ret
  653. tpardone endp
  654.  
  655. tunique    proc    far            ; reach to real unique name procedure
  656.     call    unique            ;  while in Tek mode
  657.     ret
  658. tunique    endp
  659.  
  660. tekwait    proc    far            ; call pcwait while in Tek mode
  661.     call    pcwait
  662.     ret
  663. tekwait    endp
  664.  
  665.  
  666. ; Return screen info for Tek screen report: ax=screen height, bx=width,
  667. ; cx=number of colors (0=none for pure text, 1=b/w, 16=ega)
  668. tekinq    proc    near
  669.     mov    tekident,1        ; say this is an ident request
  670.     call    dword ptr initptr    ; do init steps to get screen sizes
  671.     mov    ax,ybot            ; lowest screen line
  672.     inc    ax            ; screen height, in lines
  673.     mov    bx,xmax
  674.     add    bx,8            ; screen width, in dots
  675.     cmp    graph_mode,mono        ; pure text mono (no graphics at all)?
  676.     jne    tekinq1            ; ne = no
  677.     mov    ax,24            ; bottom screen line
  678.     mov    bx,80            ; screen width
  679.     xor    cx,cx            ; pure mono, say 0 colors
  680.     jmp    short tekinq2
  681. tekinq1:mov    cx,1            ; say b/w screen
  682.     cmp    plotptr,offset pltcga    ; using CGA style graphics?
  683.     je    tekinq2            ; e = yes
  684.     cmp    graph_mode,monoega    ; monochrome monitor on ega?
  685.     je    tekinq2            ; e = yes
  686.     mov    cx,16            ; say 16 colors
  687. tekinq2:mov    tekident,0
  688.     ret
  689. tekinq    endp
  690.  
  691. ; Return in BX the offset of the master color palette table. Used by SET TERM
  692. ; GRAPHICS COLOR <color value> to obtain foreground and background colors
  693. ; in palette slots 7 and 0, resp.
  694. tekgcptr proc    near
  695.     mov    tekident,1        ; say this is an ident request
  696.     call    dword ptr initptr    ; do init steps to get screen sizes
  697.     mov    bx,offset mondef    ; default monochrome colors
  698.     cmp    plotptr,offset pltcga    ; using CGA style graphics?
  699.     je    tekgcpt1        ; e = yes
  700.     cmp    graph_mode,mono        ; pure mono text system?
  701.     je    tekgcpt1        ; e = yes
  702.     cmp    graph_mode,monoega    ; ega, but monochrome?
  703.     je    tekgcpt1        ; e = no
  704.     mov    bx,offset coldef    ; return offset of color palette
  705. tekgcpt1:mov    havepal,0        ; say don't have a palette setup
  706.     mov    tekident,0
  707.     mov    inited,0
  708.     ret
  709. tekgcptr endp
  710.  
  711. ; These routines can be called by either the main body or from within Tek
  712. ; mode.
  713. tekdmp    proc    near            ; Tek screen dump routine
  714.     call    dword ptr dumpptr    ; callable from main body
  715.     clc
  716.     ret
  717. tekdmp    endp
  718.  
  719. tekmac    proc    far            ; invoke vtrmac or vtsmac
  720.     or    ax,ax            ; which macro?
  721.     jz    tekmacr            ; z = the R flavor
  722.     call    vtsmac            ; do TerminalS, in msyibm
  723.     ret
  724. tekmacr:call    vtrmac            ; do TerminalR, in msyibm
  725.     ret                ; only if they fail
  726. tekmac    endp
  727.  
  728. tekpal    proc    near            ; do palette report tekrpt
  729.     call    dword ptr rptptr    ; callable from main body
  730.     ret
  731. tekpal    endp
  732.  
  733. tekrpal    proc    near            ; restore color palette
  734.     call    dword ptr tekpptr    ; callable from main body
  735.     ret
  736. tekrpal endp
  737. code    ends                ; main body code segment
  738.  
  739. ; Code segment code2 is allocated to Tektronix emulation
  740. code2    segment                ; supplementary code segment
  741.  
  742.     assume    cs:code2, ds:data, es:nothing
  743.  
  744. cs2pb    db    256    dup (0)        ; code2 segment patch buffer
  745.  
  746. tekxco4    proc    FAR            ; call local tekgco4, return far
  747.     call    tekgco4
  748.     ret
  749. tekxco4    endp
  750.  
  751. ; Initialise TEK mode by setting high resolution screen, etc
  752. tekini    proc    far
  753.     push    ax            ; do presence tests
  754.     push    bx
  755.     push    cx
  756.     push    dx
  757.     push    si
  758.     push    di
  759.     push    es
  760.     cmp    tekident,0        ; just identifying?
  761.     jne    tekin0            ; ne = yes
  762.     mov    bx,portval        ; get port flow control chars:
  763.     mov    bx,[bx].flowc        ; bh=xon, bl=xoff or both are nulls
  764.     mov    flow,bx            ; save here
  765.     mov    ax,bx            ; get flow control word
  766.     or    al,al            ; able to do xoff?
  767.     jz    tekin0            ; z = no
  768.     call    outmodem        ; tell host xoff while we change modes
  769. tekin0:    cmp    inited,0        ; inited yet?
  770.     jne    tekin0a            ; ne = yes, use existing coloring
  771.     mov    ax,linetab        ; get default line pattern
  772.     mov    linepat,ax        ; init active line pattern
  773.     mov    fillptr,offset filpat1    ; init active fill pointer
  774.     cmp    havepal,0        ; have a color palette yet?
  775.     jne    tekin0a            ; ne = yes
  776.     mov    bx,vtemu.att_ptr    ; emulator screen color ptr
  777.     mov    al,[bx]
  778.     mov    gfcol,al        ; save foreground color
  779.     and    gfcol,0fh        ; save just foreground bits
  780.     and    al,70h            ; select background color, no bold
  781.     mov    cl,4
  782.     shr    al,cl            ; get background colors
  783.     mov    gbcol,al        ; set graphics background color
  784. tekin0a:mov    ah,15            ; get current screen mode
  785.     int    screen
  786.     and    al,not 80h        ; strip "preserve regen" bit 80h
  787.     cmp    al,mono            ; mono text mode (7)?
  788.     je    tekin1            ; e = yes
  789.     cmp    tekident,0        ; doing an ident request?
  790.     jne    tekin2            ; ne = yes, don't mess with screen
  791.     test    tekflg,1        ; are we active as Tek device now?
  792.     jz    tekin1            ; z = no
  793.     jmp    tekin13            ; yes, don't redo graphics setup
  794. tekin1:    mov    curmode,al        ; save mode here
  795.     mov    ah,3            ; get cursor position
  796.     xor    bh,bh            ; page 0
  797.     int    screen
  798.     mov    cursor,dx        ; save position
  799.     call    tsavescr        ; save text screen
  800.                     ; Presence tests.
  801. tekin2:    mov    graph_mode,cga        ; Color. Assume CGA
  802.     mov    segscn,segcga        ; assume cga screen segment
  803.     mov    gpage,0            ; graphics page 0 but no page 1
  804.     mov    putc,offset gputc    ; CGA character display routine
  805.     mov    gfplot,offset bpltcga    ; CGA area fill routine
  806.     mov    psetup,offset psetupc    ; CGA plot setup routine
  807.     mov    plotptr,offset pltcga    ; CGA dot plot routine
  808.     mov    pincy,offset pincyc    ; CGA inc y routine
  809.     mov    xmult,5            ; CGA. Scale TEK to PC by 640/1024
  810.     mov    xdiv,8            ;  so that 0-1023 converts to 0-639
  811.     mov    xmax,640-8        ; x-coord of rightmost character
  812.     mov    ymult,10        ; vertical scale for IBM is 200/780
  813.     mov    ydiv,39            ;
  814.     mov    ybot,199        ; Bottom of screen is Y=199
  815.     mov    al,tekgraf        ; user video board specification
  816.     or    al,al            ; auto-sensing?
  817.     jnz    tekin2d            ; nz = no
  818.     jmp    tekin2c            ; yes (default)
  819. tekin2d:cmp    al,1            ; user wants CGA?
  820.     jne    tekin2a            ; ne = no
  821.     jmp    tekin13            ; do CGA
  822. tekin2a:cmp    al,4            ; user wants Hercules?
  823.     jne    tekin2b            ; ne = no
  824.     jmp    tekin8            ; do Hercules
  825. tekin2b:cmp    al,5            ; user wants AT&T style?
  826.     jne    tekinwy            ; ne = no
  827.     jmp    tekin7            ; do AT&T kind
  828.                     ; Wyse-700
  829. tekinwy:cmp    al,8            ; user wants Wyse-700 1024*780 ?
  830.     jne    tekinw0            ; ne = no
  831.     call    chkwyse            ; presence test
  832.     jc    tekinwf            ; c = failed
  833.     mov    xmax,1024-8        ; x-coord of rightmost character
  834.     mov    ybot,779        ; Bottom of screen is Y=780
  835.     mov    xmult,1            ; Wyse. Scale TEK to PC by 1024/1024
  836.     mov    xdiv,1            ;  so that 0-1023 converts to 0-1023
  837.     mov    ymult,1            ; vertical scale is 780/780
  838.     mov    ydiv,1            ;
  839.     jmp    short tekinw2        ;
  840. tekinw0:cmp    al,7            ; user wants Wyse-700 1280*780 ?
  841.     jne    tekinw1            ; ne = no
  842.     call    chkwyse            ; presence test
  843.     jc    tekinwf            ; c = failed
  844.     mov    xmax,1280-8        ; x-coord of rightmost character
  845.     mov    ybot,779        ; Bottom of screen is Y=800
  846.     mov    xmult,10        ; Wyse. Scale TEK to PC by 1280/1024
  847.     mov    xdiv,8            ;  so that 0-1023 converts to 0-1279
  848.     mov    ymult,1            ; vertical scale is 780/780
  849.     mov    ydiv,1            ;
  850.     jmp    short tekinw2        ;
  851. tekinwf:jmp    tekin2c            ; failure jump point
  852. tekinw1:cmp    al,6            ; user wants Wyse-700 1280*800 ?
  853.     jne    tekin2c            ; no = no
  854.     call    chkwyse            ; presence test
  855.     jc    tekinwf            ; c = failed
  856.     mov    xmax,1280-8        ; x-coord of rightmost character
  857.     mov    ybot,799        ; Bottom of screen is Y=800
  858.     mov    xmult,10        ; Wyse. Scale TEK to PC by 1280/1024
  859.     mov    xdiv,8            ;  so that 0-1023 converts to 0-1279
  860.     mov    ymult,40        ; vertical scale for IBM is 800/780
  861.     mov    ydiv,39            ;  so scale those 20 pixels more
  862. tekinw2:mov    graph_mode,wyse700    ; Assume Wyse Graphics
  863.     mov    segscn,segwyse        ; assume wyse screen segment
  864.     mov    gpage,0            ; only one graphics page 0
  865.     mov    putc,offset gputc    ; CGA character display routine
  866.     mov    psetup,offset psetupw    ; Wyse plot setup routine
  867.     mov    plotptr,offset pltcga    ; CGA dot plot routine
  868.     mov    pincy,offset pincyw    ; Wyse inc y routine
  869.     jmp    tekin13            ; do Wyse
  870.                     ; do auto-sensing of display board
  871.                     ; test for EGA
  872. tekin2c:mov    ax,1200H        ; EGA: Bios alternate select
  873.     mov    bl,10H                  ; Ask for EGA info
  874.     mov    bh,0ffH            ; Bad info, for testing
  875.     mov    cl,0fH            ; Reserved switch settings
  876.     int    screen            ; EGA, are you there?
  877.     and    cl,0fh            ; four lower switches
  878.     cmp    cl,0cH            ; Test reserved switch settings
  879.     jb    tekin3            ; b = ega present
  880.     jmp    tekin7            ; else no EGA, check other adapters
  881.  
  882. tekin3:    mov    ax,40h            ; check Bios 40:87h for ega being
  883.     mov    es,ax            ;  the active display adapter
  884.     test    byte ptr es:[87h],8    ; is ega active?
  885.     jz    tekin3a            ; z = yes
  886.     jmp    tekin7            ; ega is inactive, check others
  887. tekin3a:cmp    bl,1            ; is there 128KB on ega board?
  888.     jb    tekin4            ; b = less, so no screen saves
  889.     mov    gpage,1            ; >=128 KB, use two graphics pages
  890. tekin4:    mov    graph_mode,ega        ; assume high resolution color
  891.     cmp    cl,3            ; high resolution color?
  892.     je    tekin5            ; e = yes
  893.     cmp    cl,9            ; high resolution color?
  894.     je    tekin5            ; e = yes
  895.     mov    graph_mode,monoega    ; assume mono monitor on ega board
  896.     test    bh,1            ; ega mono mode in effect?
  897.      jnz    tekin5            ; nz = yes
  898.     mov    graph_mode,colorega    ; say ordinary cga on ega board, 64KB
  899.     mov    gpage,1            ; is enough memory with 200 scan lines
  900.     jmp    short tekin5a        ; use current cga parameters
  901. tekin5:    mov    ybot,349        ; text screen bottom is 349 on EGA
  902.     mov    ymult,35        ;
  903.     mov    ydiv,78            ; scale y by 350/780
  904. tekin5a:mov    segscn,segega        ; use ega screen segment
  905.     mov    psetup,offset psetupe    ; plot setup routine
  906.     mov    plotptr,offset pltega    ; ega dot plot routine
  907.     mov    gfplot,offset bpltega    ; ega area fill routine
  908.     mov    pincy,offset pincye    ; inc y routine
  909.     mov    putc,offset gputc    ; character display routine
  910.     jmp    tekin13            ; end of EGA part, do VGA tests below
  911.  
  912. tekin7:    mov    ax,0fc00h        ; Olivetti/AT&T 6300, check rom id
  913.     mov    es,ax
  914.     xor    di,di            ; start here
  915.     mov    graph_mode,olivetti    ; Olivetti
  916.     mov    cx,attllen        ; length of logo
  917.     mov    si,offset ATTLOGO    ; master string
  918.     repe    cmpsb            ; do a match
  919.     je    tekin7c            ; e = a match
  920.     mov    di,0050h        ; look here too
  921.     mov    si,offset ATTLOGO
  922.     mov    cx,attllen
  923.     repe    cmpsb
  924.     je    tekin7c            ; e = a match
  925.     mov    di,2014h        ; and look here
  926.     mov    si,offset ATTLOGO
  927.     mov    cx,attllen
  928.     repe    cmpsb            ; do a match
  929.     je    tekin7c            ; e = a match, else try other types
  930. tekin7a:mov    graph_mode,toshiba
  931.     mov    ax,0f000h        ; Check for Toshiba T3100, rom scan
  932.     mov    es,ax
  933.     mov    di,0014h        ; start here
  934.     mov    si,offset TOSHLOGO    ; master string
  935.     mov    cx,toshlen        ; length
  936.     repe    cmpsb            ; do a match
  937.     je    tekin7c            ; e = a match, else try other types
  938. tekin7b:mov    graph_mode,vaxmate    ; DEC VAXmate II
  939.     mov    ax,0f000h        ; Check for VAXmate II rom signature
  940.     mov    es,ax
  941.     mov    di,0e000h        ; start here
  942.     mov    si,offset DECLOGO    ; master string
  943.     mov    cx,declen        ; length
  944.     repe    cmpsb            ; do a match
  945.     jne    tekin7d            ; ne = mismatch, try other types
  946.  
  947.                     ; Olivetti/AT&T, Toshiba, VAXmate
  948. tekin7c:mov    gpage,0            ; only page 0 with 640 by 400 mode
  949.     mov    segscn,segcga        ; use cga screen segment (0b800h)
  950.     mov    psetup,offset psetupo    ; plot setup routine
  951.     mov    plotptr,offset pltcga    ; cga dot plot routine
  952.     mov    gfplot,offset bpltcga    ; area fill plot routine
  953.     mov    pincy,offset pincyh    ; inc y routine (Herc style addresses)
  954.     mov    putc,offset gputc    ; character display routine
  955.     mov    ybot,399        ; bottom of screen is y = 399
  956.     mov    ymult,20        ; vertical scale = 400/780
  957.     mov    ydiv,39            ; same as cga setup
  958.     jmp    tekin13
  959.  
  960. tekin7d:cmp    curmode,mono        ; mono text mode?
  961.     je    tekin8            ; e = yes
  962.     jmp    tekin11            ; ne = no, try cga
  963.                     ; test for Hercules
  964. tekin8:    call    tscrseg            ; get screen segment, test Environment
  965.     cmp    tv_mode,1        ; Environment active?
  966.     jne    tekin8a            ; ne = no, ok to test for Hercules
  967.     jmp    tekin10            ; don't do Herc mode, do Mono
  968. tekin8a:mov    dx,hstatus        ; Herc status port
  969.     in    al,dx            ; read it
  970.     mov    bl,al            ; save here
  971.     and    bl,80h            ; remember retrace bit
  972.     mov    cx,0ffffh        ; do many times (for fast machines)
  973. tekin8b:mov    dx,hstatus        ; check status port
  974.     in    al,dx
  975.     and    al,80h            ; select bit
  976.     jmp    $+2            ; use a little time
  977.     cmp    bl,al            ; did it change?
  978.     loope    tekin8b            ; test again if not
  979.     je    tekin10            ; e = no change in bit, not Herc
  980.     mov    graph_mode,hercules    ; say have Herc board
  981.     mov    segscn,seghga        ; assume hga screen segment
  982.     mov    putc,offset gputc    ; character display routine
  983.     mov    gfplot,offset bpltcga    ; area fill plot routine
  984.     mov    psetup,offset psetuph    ; plot setup routine to use
  985.     mov    plotptr,offset pltcga    ; use cga dot plot routine for Herc
  986.     mov    pincy,offset pincyh    ; inc y routine
  987.     mov    xmult,45        ; Scale TEK to Hercules by 720/1024
  988.     mov    xdiv,64            ;  so that 0-1023 converts to 0-719
  989.     mov    xmax,720-8        ; x-coord of rightmost character
  990.     mov    ymult,87        ; vertical scale for Hercules is
  991.     mov    ydiv,195        ;  348/780
  992.     mov    ybot,347        ; bottom of screen is y = 347
  993.     mov    ax,seghga        ; segment of Herc video display
  994.     mov    es,ax
  995.     mov    al,es:[8000h]        ; read original contents, page 1
  996.     not    byte ptr es:[8000h]    ; write new pattern
  997.     mov    ah,es:[8000h]        ; read back
  998.     not    byte ptr es:[8000h]    ; restore original contents
  999.     not    ah            ; invert this too
  1000.     cmp    ah,al            ; same (memory present?)
  1001.     jne    tekin9            ; ne = not same, no memory there
  1002.     mov    gpage,1            ; say two pages of display memory
  1003. tekin9:    call    crossini        ; preset crosshairs
  1004.     jmp    tekin13
  1005.                     ; set to MONO
  1006. tekin10:mov    graph_mode,mono        ; force monochrome adapter text
  1007.     mov    segscn,segmono        ; assume mono screen segment
  1008.     call    tscrseg            ; Environments: get virtual screen
  1009.     mov    segscn,ax        ;  seg returned in ax and es:di
  1010.     mov    gpage,0
  1011.     mov    putc,offset mputc    ; character display routine
  1012.     mov    psetup,offset psetupm    ; plot setup routine to use
  1013.     mov    gfplot,offset bpltmon    ; area fill plot routine
  1014.     mov    plotptr,offset pltmon    ; use hga dot plot routine
  1015.     mov    pincy,offset pincym    ; inc y routine
  1016.     mov    xmult,5            ; Scale TEK to mono by 640/1024
  1017.     mov    xdiv,8            ;  so that 0-1023 converts to 0-639
  1018.     mov    xmax,640-8        ; x-coord of rightmost character
  1019.     mov    ymult,10        ; vertical scale for mono is 200/780
  1020.     mov    ydiv,39
  1021.     mov    ybot,200        ; bottom of screen is y = 200 for Bios
  1022.     jmp    tekin13            ; Uses TEXT mode, for safety
  1023.  
  1024.                     ; test for CGA
  1025. tekin11:mov    graph_mode,cga        ; set CGA high resolution graphics
  1026.     mov    segscn,segcga        ; CGA screen segment
  1027.     jmp    tekin13
  1028.  
  1029.                     ; Set Graphics mode
  1030. tekin13:cmp    tekident,0        ; just identifying?
  1031.     je    tekin13b        ; e = no
  1032.     jmp    tekin16            ; ne = yes
  1033. tekin13b:cmp    graph_mode,wyse700    ; Wyse ?
  1034.     jne    tekin13a        ; ne = no
  1035.     call    wygraf            ; set Wyse graphics mode, clear regen
  1036.     jmp     tekin16        ; restore screen
  1037. tekin13a:cmp    graph_mode,hercules    ; Hercules?
  1038.     jne    tekin14            ; ne = no
  1039.     call    hgraf            ; set Herc graphics mode, clear regen
  1040.     or    tekflg,1        ; say doing Tekmode
  1041.     jmp     tekin16        ; restore screen
  1042. tekin14:xor    ah,ah            ; set screen mode
  1043.     mov    al,graph_mode        ;  to this screen mode
  1044.     cmp    tekgraf,3        ; user wants "VGA" modes (640x480)?
  1045.     jne    tekin14a        ; ne = no
  1046.     push    ax
  1047.     mov    ax,1a00h        ; VGA, read display config code
  1048.     int    screen
  1049.     pop    ax
  1050.     cmp    bl,0bh            ; MCGA mono?
  1051.     jne    tekin14b        ; ne = no
  1052.     mov    al,monoega
  1053.     mov    graph_mode,al
  1054.     jmp    short tekin14c
  1055. tekin14b:cmp    bl,0ch            ; MCGA color?
  1056.     jne    tekin14d        ; ne = no
  1057.     mov    al,ega
  1058.     mov    graph_mode,al
  1059. tekin14c:mov    ydiv,78            ; scale y by 350/780
  1060.     mov    segscn,segega        ; use ega screen segment
  1061.     mov    psetup,offset psetupe    ; plot setup routine
  1062.     mov    plotptr,offset pltcga    ; ega dot plot routine
  1063.     mov    gfplot,offset bpltcga    ; ega area fill routine
  1064.     mov    pincy,offset pincye    ; inc y routine
  1065.     mov    putc,offset gputc    ; character display routine
  1066. tekin14d:
  1067.     cmp    al,monoega        ; yes, allow high resolution stuff?
  1068.     jb    tekin14a        ; b = no
  1069.     cmp    al,ega            ; ditto
  1070.     ja    tekin14a        ; a = no
  1071.     add    al,2            ; use modes 17(b/w) and 18(10)(color)
  1072.     mov    ybot,479        ; text screen bottom is 479 on VGA
  1073.     mov    ymult,48
  1074. tekin14a:cmp    tekident,0        ; just identifying screen size etc?
  1075.     jne    tekin16            ; ne = yes, do not invoke graphics
  1076.     cmp    gpage,0            ; only page 0 available?
  1077.     je    tekin15            ; e = yes, and watch for Bios errors
  1078.     cmp    inited,0        ; first time through?
  1079.     je    tekin15            ; e = yes, clear the page of old junk
  1080.     or    al,80h            ; save regen buffer (save area too)
  1081. tekin15:int    screen            ; Bios Set Mode.
  1082.     mov    ax,40h            ; DOS 4 GRAPHICS.COM may see high bit
  1083.     mov    es,ax            ;  and be confused. Clear it from Bios
  1084.     and    byte ptr es:[49h],7fh    ;  word area for some clones
  1085.     or    tekflg,1        ; say doing Tekmode
  1086.  
  1087. tekin16:cmp    tekident,0        ; just identifying?
  1088.     jne    tekin16a        ; ne = yes
  1089.     cmp    inited,0        ; inited yet?
  1090.     jne    tekin19            ; ne = yes, restore screen
  1091.     mov    ttstate,offset tektxt    ; do displayable text
  1092.     mov    prestate,offset tektxt    ; set a previous state of text
  1093.     mov    inited,1        ; say we have initialized
  1094.     jmp    short tekin16b        ; and init the color palette
  1095. tekin16a:mov    si,offset colpal    ; active color palette
  1096.     cmp    havepal,0        ; have a color palette yet?
  1097.     jne    tekin17            ; yes, use active palette
  1098. tekin16b:mov    si,offset mondef    ; default monochrome colors
  1099.     cmp    plotptr,offset pltcga    ; using CGA style graphics?
  1100.     je    tekin17            ; e = yes
  1101.     cmp    graph_mode,mono        ; pure mono text system?
  1102.     je    tekin17            ; e = yes
  1103.     cmp    graph_mode,monoega    ; ega, but monochrome?
  1104.     je    tekin17            ; e = no
  1105.     mov    si,offset coldef    ; use color palette
  1106. tekin17:mov    havepal,1        ; say have a color palette
  1107.     mov    al,[si+7]        ; foreground color = palette 7
  1108.     mov    gfcol,al
  1109.     mov    al,[si]            ; background color = palette 0
  1110.     mov    gbcol,al
  1111.     mov    cx,16
  1112.     mov    di,offset colpal    ; VT340 active color palette
  1113.     push    es
  1114.     push    ds
  1115.     pop    es
  1116.     cld
  1117.     rep    movsb            ; reinit palette entries
  1118.     pop    es
  1119.     call    fixcolor        ; correct color mapping for some bds
  1120.     mov    al,gfcol
  1121.     mov    tfcol,al        ; remember current coloring
  1122.     mov    al,gbcol
  1123.     mov    tbcol,al
  1124.     cmp    tekident,0        ; just identifying?
  1125.     jne    tekin21            ; ne = yes
  1126.     call    tekcls            ; clear screen, for ega coloring
  1127.     jmp    short tekin20
  1128.  
  1129. tekin19:cmp    vtclear,0        ; clear screen?
  1130.     je    tekin19a        ; e = no
  1131.     call    tekcls            ; clear screen, use existing colors
  1132.     jmp    short tekin20
  1133. tekin19a:call    tekrest            ; restore old graphics screen
  1134.     mov    al,tfcol        ; and coloring
  1135.     mov    gfcol,al
  1136.     mov    al,tbcol
  1137.     mov    gbcol,al
  1138. tekin20:call    setcursor        ; set text cursor, if any
  1139.     mov    ax,250
  1140.     call    tekwait            ; 250 ms wait for display adapter
  1141.     mov    ax,flow            ; get flow control word
  1142.     xchg    ah,al            ; get xon into al
  1143.     or    al,al            ; able to send xon?
  1144.     jz    tekin21            ; z = no
  1145.     call    outmodem        ; tell host xon
  1146. tekin21:mov    al,chcontrol        ; opaque/transparent char writing
  1147.     mov    bscontrol,al        ; set destructive BS control
  1148.     mov    spcontrol,al        ; set destructive SPACE control
  1149.     mov    tekident,0
  1150.     mov    bypass,0        ; clear Bypass flag
  1151.     clc                ; clear carry for success
  1152.     pop    es
  1153.     pop    di
  1154.     pop    si
  1155.     pop    dx
  1156.     pop    cx
  1157.     pop    bx
  1158.     pop    ax
  1159.     ret
  1160. tekini    endp
  1161.  
  1162. TEKRINT proc    far            ; Tek reinitialization entry point
  1163.     call    dword ptr endptr    ; exit cleanly if alread in Tek mode
  1164.     xor    ax,ax            ; get a null
  1165.     mov    inited,al        ; do complete reinitialization
  1166.     mov    tekflg,al
  1167.     mov    xcenter,ax        ; forget center of screen
  1168.     mov    ycenter,ax
  1169.     call    tekini
  1170.     ret
  1171. TEKRINT    endp
  1172.  
  1173. ; End TEK emulation, recover previous screen
  1174. TEKEND    proc    far
  1175.     mov    ttstate,offset tektxt    ; set an initial state
  1176.     mov    prestate,offset tektxt    ; and a previous state
  1177.     test    tekflg,1        ; running as a Tek terminal now?
  1178.     jnz    teknd1            ; nz = yes
  1179.     mov    tekflg,0        ; returning to text emulator
  1180.     ret                ; else return as is
  1181. teknd1:    call    remcursor        ; remove text cursor, if any
  1182.     call    teksave            ; save graphics screen to page 1
  1183.     cmp    graph_mode,hercules    ; Hercules?
  1184.     jne    teknd2            ; ne = no
  1185.     call    htext            ; yes then set up Hercules text mode
  1186. teknd2:    call    mousexit        ; restore mouse state, if any
  1187.     xor    ah,ah            ; set video mode
  1188.     mov    al,curmode        ; restore previous screen mode
  1189.     int    screen            ; revert to text screen
  1190.     call    trestscr        ; restore text screen
  1191.     mov    dx,cursor        ; saved cursor position
  1192.     xor    bh,bh            ; page 0
  1193.     mov    ah,2            ; set cursor
  1194.     int    screen
  1195.     mov    tekflg,0        ; returning to text emulator
  1196.     mov    lastc,0
  1197.     mov    bypass,0        ; reset bypass condition
  1198.     mov    visible,0        ; next move is invisible
  1199.     clc
  1200.     ret
  1201. TEKEND    ENDP
  1202.  
  1203.  
  1204. ;Terminal emulation. Enter with received character in AL.
  1205. TEKEMU    proc    far            ; main emulator
  1206.     call    tektt            ; local emulator routine
  1207.     ret
  1208. TEKEMU    endp
  1209.  
  1210. tektt    proc    near
  1211.     test    tekflg,1        ; running as a Tek device?
  1212.     jnz    tektt1            ; nz = yes
  1213.     push    ax
  1214.     call    tekini            ; init now
  1215.     pop    ax
  1216.     mov    ttstate,offset tektxt    ; initial state
  1217.     mov    prestate,offset tektxt    ; set a previous state of text
  1218.     jnc    tektt1            ; nc = succeeded
  1219.     ret                ; else failed to init, just return
  1220. tektt1:    test    al,80h            ; high bit set?
  1221.     jz    tektt1a            ; z = no
  1222.     cmp    al,9fh            ; in range for C1 controls?
  1223.     ja    tektt1a            ; a = no
  1224.     push    ax            ; save the char
  1225.     mov    al,escape        ; make 7-bit control version
  1226.     call    tektt2            ; act on escape
  1227.     pop    ax
  1228.     sub    al,40h            ; get second char of 7-bit control
  1229.  
  1230. tektt1a:and    al,7fh            ; force Tek chars to be 7 bits
  1231.     or    al,al            ; NUL char?
  1232.     jnz    tektt2            ; nz = no
  1233.     ret                ; yes, ignore it (before logging)
  1234. tektt2:    test    yflags,capt        ; capturing output?
  1235.     jz    tektt4            ; z = no, forget this part
  1236.     push    ax            ; save char
  1237.     call    tcptchr            ; give it captured character
  1238.     pop    ax            ; restore character and keep going
  1239. tektt4:    test    yflags,trnctl        ; debug? if so use tty mode
  1240.     jz    tektt5            ; z = no
  1241.     cmp    al,DEL            ; DEL char?
  1242.     jne    tektt4a            ; ne = no
  1243.     mov    al,5eh            ; make DEL a caret query mark
  1244.     call    outscrn
  1245.     mov    al,3fh            ; the query mark
  1246.     call    outscrn
  1247.     ret
  1248. tektt4a:cmp    al,' '            ; control char?
  1249.     jae    tektt4b            ; ne = no
  1250.     push    ax
  1251.     mov    al,5eh            ; caret
  1252.     call    outscrn
  1253.     pop    ax
  1254.     add    al,'A'-1        ; make char printable
  1255. tektt4b:call    outscrn
  1256.     ret
  1257.  
  1258. tektt5:    cmp    bypass,0        ; Bypass mode off?
  1259.     jne    tektt5a            ; ne = no, on, ignore all incoming
  1260.     call    ttstate            ; do current state
  1261.     ret
  1262. tektt5a:cmp    al,' '            ; incoming control code?
  1263.     jae    tektt5b            ; ae = no
  1264.     mov    bypass,0        ; turn off bypass
  1265.     call    ttstate            ; act on it
  1266. tektt5b:ret
  1267. tektt    endp
  1268.      
  1269. TEKTXT    proc    near            ; Dispatch on text characters
  1270.     mov    ttstate,offset tektxt    ; this is our state
  1271.     push    ax
  1272.     call    setcursor        ; show text cursor
  1273.     pop    ax
  1274.     cmp    al,DEL            ; RUBOUT?
  1275.     jne    tektx1            ; ne = no
  1276.     mov    al,bs            ; make BS
  1277.     jmp    short tektx7
  1278. tektx1:    cmp    al,CR            ; carriage return (^M)?
  1279.     je    tektx7            ; e = yes
  1280.     cmp    al,LF            ; line feed (^J)?
  1281.     je    tektx7            ; e = yes
  1282.     cmp    al,FF            ; form feed (^L)?
  1283.     jne    tektx4            ; ne = no
  1284.     call    tekcls            ; clear the screen
  1285.     ret
  1286. tektx4:    cmp    al,VT            ; vertical tab (^K)?
  1287.     je    tektx7
  1288.     cmp    al,bell            ; bell (^G)?
  1289.     jne    tektx5            ; ne = no
  1290.     call    tekbeep
  1291.     ret
  1292. tektx5:    cmp    al,tab            ; horizontal tab (^I)?
  1293.     je    tektx7            ; e = yes
  1294.     cmp    al,BS            ; backspace (^H)?
  1295.     je    tektx7            ; e = yes
  1296.     cmp    al,' '            ; control char?
  1297.     jae    tektx7            ; ae = no
  1298.     jmp    tekctl            ; process control char
  1299. tektx7:    call    outscrn            ; output character to the screen
  1300. tektx8:    ret
  1301. TEKTXT    endp
  1302.  
  1303.  
  1304. tekctl    proc    near            ; Control characters:
  1305.     cmp    al,GS            ; Line plot command?
  1306.     jne    tekctl1            ; ne = no
  1307.     mov    visible,0        ; next move is invisible
  1308.     and    status,not txtmode    ; set status report byte
  1309.     mov    ttstate,offset tekline    ; expect coordinates next
  1310.     call    remcursor        ; remove text cursor
  1311.     ret
  1312. tekctl1:cmp    al,RS            ; Incremental dot command?
  1313.     jne    tekctl2            ; ne = no
  1314.     and    status,not txtmode    ; set status report
  1315.     mov    ttstate,offset tekrlin    ; expect pen command next
  1316.     call    remcursor        ; remove text cursor
  1317.     ret
  1318. tekctl2:cmp    al,FS            ; Point plot command?
  1319.     jne    tekctl3            ; ne = no
  1320.     mov    visible,0        ; next move is invisible
  1321.     and    status,not txtmode    ; set status report byte
  1322.     mov    ttstate,offset tekpnt
  1323.     call    remcursor        ; remove text cursor
  1324.     ret
  1325. tekctl3:cmp    al,US            ; assert text mode? [bjh]
  1326.     jne    tekctl4            ; ne = no
  1327.     or    status,txtmode        ; set status report byte
  1328.     mov    ttstate,offset tektxt    ; go to TEKTXT next time
  1329.     mov    visible,0        ; next move is invisible
  1330.     call    setcursor        ; restore text cursor
  1331.     ret
  1332. tekctl4:cmp    al,ESCAPE        ; Escape?
  1333.     jne    tekctl5            ; ne = no
  1334.     call    remcursor        ; remove text cursor
  1335.     or    status,txtmode        ; set status report byte
  1336.     cmp    ttstate,offset tekesc    ; already in escape state?
  1337.     je    tekctl7            ; e = yes, nest no further
  1338.     push    ttstate            ; current state
  1339.     pop    prestate        ; save here as previous state
  1340.     mov    ttstate,offset tekesc    ; next state parses escapes
  1341.     ret
  1342.  
  1343. tekctl5:cmp    al,CAN            ; Control X? (exits Tek sub mode)
  1344.     jne    tekctl7            ; ne = no, stay in current state
  1345.     mov    ttstate,offset tektxt    ; back to text mode
  1346.     mov    bypass,1        ; turn on bypass mode
  1347.     cmp    flags.vtflg,tttek    ; main Tek emulator?
  1348.     je    tekctl6            ; e = yes, ignore the ^X
  1349.     call    tekend            ; else exit sub mode
  1350.     mov    visible,0        ; next move is invisible
  1351. tekctl6:mov    prestate,offset tektxt    ; make previous state text
  1352. tekctl7:ret
  1353. tekctl    endp
  1354.  
  1355. TEKESC    proc    near            ; Process ESC <following text>
  1356.     mov    ninter,0        ; initialize parsing
  1357.     mov    ttstate,offset tekesc    ; in case get here from msz file
  1358.     cmp    inited,0        ; inited yet? (msz call)
  1359.     jne    tekesc1            ; ne = yes
  1360.     call    tekini            ; init now
  1361.     mov    prestate,offset tektxt    ; set a previous state of text
  1362.     jnc    tekesc1            ; nc = succeeded
  1363.     ret                ; else failed to init, just return
  1364.     
  1365. tekesc1:cmp    al,20h            ; in intermediates, column 2?
  1366.     jb    tekesc3            ; b = no
  1367.     cmp    al,2fh
  1368.     ja    tekesc3            ; a = no
  1369.     mov    ttstate,offset tekesc1    ; stay in this state while intermeds
  1370.     mov    bx,ninter        ; number of intermediates
  1371.     cmp    bx,maxinter        ; done enough already?
  1372.     jae    tekesc2            ; ae = yes, ignore the excess
  1373.     mov    inter[bx],al        ; store this one
  1374.     inc    ninter            ; one more
  1375.     cmp    inter,'/'        ; HDS2000/3000 Final char?
  1376.     je    tekesc3            ; e = yes, process specially like '['
  1377. tekesc2:ret                ; get more input
  1378.     
  1379.                     ; Final char is in AL, dispatch on it
  1380. tekesc3:mov    ttstate,offset tektxt    ; set new state
  1381.     mov    esctype,al        ; save kind of escape sequence
  1382.     mov    bx,offset esctab    ; ESC dispatch table
  1383.     call    atdispat        ; dispatch on AL
  1384.     ret
  1385. TEKESC    endp    
  1386.  
  1387. tekeseq    proc    near            ; process Escape and Device Contrl seq
  1388.     call    tparstart        ; init escape sequence parser
  1389.     mov    ttstate,offset escparse    ; do parsing next
  1390.     ret
  1391. tekeseq    endp
  1392.  
  1393. ; State for gathering text to feed escape sequence parser
  1394. escparse proc    near
  1395.     cmp    al,' '            ; embedded control code?
  1396.     jb    escpar2            ; b = yes, process now
  1397.     call    tparser            ; far call, to call real parser
  1398.     jnc    escpar1            ; nc = success
  1399.     push    prestate        ; recover previous state
  1400.     pop    ttstate
  1401.     stc
  1402. escpar1:ret
  1403. escpar2:call    tekctl            ; process embedded control code
  1404.     push    prestate        ; get previous state
  1405.     pop    ttstate            ; restore it
  1406.     ret
  1407. escparse endp
  1408.  
  1409. ; Escape sequence parser completion routine
  1410. ; AL has Final character of escape sequence
  1411. XPARDONE PROC    FAR            ; called by tpardone when done
  1412.     cmp    esctype,'['        ; ansi escape sequence (ESC [)?
  1413.     jne    xpardo3            ; ne = no
  1414.     mov    bx,offset anstab    ; ANSI ESC [ table
  1415.     call    atdispat        ; dispatch on Final char in AL
  1416.     jmp    short xpardo5
  1417.  
  1418. xpardo3:cmp    esctype,'/'        ; HDS escape sequence (ESC /)?
  1419.     jne    xpardo4            ; ne = no
  1420.     call    hdsesc            ; analyze
  1421.     jmp    short xpardo5
  1422.  
  1423. xpardo4:cmp    esctype,'P'        ; DCS introducer?
  1424.     jne    xpardo5            ; ne = no
  1425.     call    tekdcs            ; grab parameters etc, prep strings
  1426.     ret
  1427.  
  1428. xpardo5:push    prestate        ; recover previous state
  1429.     pop    ttstate
  1430.     ret
  1431. XPARDONE ENDP
  1432.                 ; ESC <char> action routines
  1433.                 ; exit each by putting prestate into ttstate
  1434.  
  1435. tekenq    proc    near            ; ESC-^E Enquiry for cursor position
  1436.     mov    bypass,1        ; set bypass mode
  1437.     call    sendstat        ; send status
  1438.     push    prestate        ; get previous state
  1439.     pop    ttstate            ; restore it
  1440.     ret
  1441. tekenq    endp
  1442.  
  1443. tekcan    proc    near            ; ESC ^X
  1444.     push    prestate        ; get previous state
  1445.     pop    ttstate            ; restore it
  1446.     jmp    tekctl            ; process in controls section
  1447. tekcan    endp
  1448.  
  1449. tekgin    proc    near            ; ESC-^Z Enter GIN mode
  1450.     cmp    graph_mode,mono        ; Monochrome text mode?
  1451.     je    tekgin1            ; e = yes, no crosshairs in text mode
  1452.     mov    bypass,1        ; turn on GIN mode bypass conditon
  1453.     call    crossini        ; preset crosshairs
  1454.     call    croshair        ; activate the cross-hairs
  1455.     jmp    short tekgin2
  1456. tekgin1:call    tekbeep            ; tell the user we are unhappy
  1457. tekgin2:push    prestate        ; get previous state
  1458.     pop    ttstate            ; restore it
  1459.     ret
  1460. tekgin    endp
  1461.  
  1462. tektwo    proc    near            ; ESC 2 (Exit Tek mode)
  1463.     mov    al,CAN            ; force Control-X
  1464.     jmp    tekcan            ; process there as ESC ^X
  1465. tektwo    endp
  1466.  
  1467. tekqury    proc    near            ; query mark (ESC ? means DEL)
  1468.     mov    al,DEL            ; replace with DEL code
  1469.     push    prestate        ; get previous state
  1470.     pop    ttstate            ; restore it
  1471.     ret
  1472. tekqury    endp
  1473.  
  1474. tekfill    proc    near            ; Fill series ESC @ .. ESC M
  1475.     sub    al,'@'            ; remove bias
  1476.     mov    bl,al
  1477.     xor    bh,bh
  1478.     shl    bx,1            ; make a word index
  1479.     mov    bx,fillist[bx]        ; get pointer to the pattern from list
  1480.     mov    fillptr,bx        ; assign this pattern pointer
  1481.     push    prestate        ; get previous state
  1482.     pop    ttstate            ; restore it
  1483.     ret
  1484. tekfill    endp
  1485.  
  1486. teklpat    proc    near            ; ESC accent grave line pattern series
  1487.     cmp    al,'g'            ; accent ... lowercase g?
  1488.     jbe    teklpa2            ; be = yes
  1489.     cmp    al,'o'            ; bold patterns ESC h..ESC o?
  1490.     ja    teklpa1            ; a = no
  1491.     sub    al,'h'-accent        ; map bold to normal
  1492.     jmp    short teklpa2
  1493. teklpa1:sub    al,'x'-'f'        ; user sets,map x to f, y to g, z to h
  1494. teklpa2:push    bx
  1495.     mov    bl,al
  1496.     sub    bl,accent        ; remove bias
  1497.     cmp    bl,8            ; nine patterns, ignore others
  1498.     jbe    teklpa3            ; be = ok, make others accent, solid
  1499.     xor    bl,bl            ; solid pattern
  1500. teklpa3:xor    bh,bh
  1501.     shl    bx,1            ; make this a word index
  1502.     mov    bx,linetab[bx]        ; get line pattern word
  1503.     mov    linepat,bx        ; save in active word
  1504.     pop    bx            ; return to previous mode
  1505.     push    prestate        ; get previous state
  1506.     pop    ttstate            ; restore it
  1507.     ret
  1508. teklpat    endp
  1509.  
  1510. ; Detect exit Tek submode command ESC [ ? 38 l  from VT340's
  1511. escexit    proc    near
  1512.     cmp    lparam,'?'        ; possible "ESC [ ? 38 l"?
  1513.     jne    escex2            ; ne = no
  1514.     cmp    nparam,1        ; just one numeric parameter?
  1515.     jne    escex2            ; ne = no
  1516.     cmp    al,'l'            ; ESC [ ? Pn l?
  1517.     jne    escex4            ; ne = no, try 'h'
  1518.     cmp    param,38        ; correct value?
  1519.     jne    escex3            ; ne = no
  1520.     cmp    flags.vtflg,tttek    ; are we a full Tek terminal now?
  1521.     je    escex1            ; e = yes, stay that way
  1522.     call    dword ptr endptr    ; call far tekend
  1523.     ret
  1524. escex1:    mov    ttstate,offset tektxt
  1525.     mov    al,CAN            ; simulate arrival of Control-X
  1526.     jmp    tektxt            ; process char as text
  1527. escex2:    ret
  1528. escex3:    cmp    param,34        ; ESC [ ? 34 l?
  1529.     jne    escex2            ; ne = no
  1530.     call    tekend            ; play safe and restore text mode
  1531.     xor    ax,ax            ; tell tekmac it's a Reset flavor
  1532.     call    tekmac            ; returns only if successful
  1533.     ret
  1534. escex4:    cmp    al,'h'            ; ESC ... h?
  1535.     jne    escex3            ; ne = no
  1536.     cmp    param,34        ; ESC [ ? 34 h?
  1537.     jne    escex2            ; ne = no
  1538.     call    tekend            ; play safe and restore text mode
  1539.     mov    ax,1            ; tell tekmac it's a Set flavor
  1540.     call    tekmac            ; returns only if successful
  1541.     ret
  1542. escexit    endp
  1543.  
  1544. ; Human Data Systems 2000/3000 style escape sequences (ESC / params Final)
  1545. ; Final character is in AL
  1546. hdsesc    proc    near
  1547.     cmp    al,'x'            ; draw an empty rectangle?
  1548.     jne    hdsesc0            ; ne = no
  1549.     call    rectdraw
  1550.     jmp    short hdsesc2a
  1551. hdsesc0:cmp    al,'y'            ; draw a filled rectangle?
  1552.     jne    hdsesc1            ; ne = no
  1553.     call    rectfil            ;do xhome,yhome,xwidth,yheight,pattern
  1554.     jmp    short hdsesc2a
  1555. hdsesc1:cmp    al,'z'            ; draw and fill rectangle?
  1556.     jne    hdsesc2            ; ne = no
  1557.     call    rectfil            ; do fill before border
  1558.     call    rectdraw        ; do border
  1559.     jmp    short hdsesc2a
  1560. hdsesc2:cmp    ninter,0        ; any intermediates?
  1561.     jne    hdsesc2a        ; ne = yes, failure
  1562.     cmp    lparam,0        ; letter parameter?
  1563.     jne    hdsesc2a        ; ne = yes, failure
  1564.     cmp    nparam,1        ; just zero or one numeric parameter?
  1565.     ja    hdsesc9            ; a = no
  1566.     cmp    al,'a'            ; user defined pattern?
  1567.     jb    hdsesc3            ; b = no
  1568.     cmp    al,'c'
  1569.     ja    hdsesc3            ; a = no
  1570.     sub    al,'a'            ; 'a' is first of three user patterns
  1571.     xor    ah,ah            ;  store as 'f,g,h' in the series
  1572.     mov    bx,ax
  1573.     shl    bx,1            ; make a word index
  1574.     mov    ax,param[0]        ; get the 16-bit pattern
  1575.     mov    linetab[bx+12],ax    ; store in user defined pattern
  1576. hdsesc2a:push    prestate        ; get previous state
  1577.     pop    ttstate            ; restore it
  1578.     ret
  1579.  
  1580. hdsesc3:cmp    al,'d'            ; "Data Level" (pixel ops)?
  1581.     jne    hdsesc4            ; ne = no
  1582.     mov    cx,param        ; get the parameter value
  1583.     mov    al,pixfor        ; assume foreground only ESC / 0 d
  1584.     cmp    cl,1            ; something else?
  1585.     jb    hdsesc3a        ; b = no
  1586.     mov    al,pixbak        ; assume background only ESC / 1 d
  1587.     cmp    cl,2            ; something else?
  1588.     jb    hdsesc3a        ; b = no
  1589.     mov    al,pixxor        ; assume XOR  ESC / 2 d
  1590.     cmp    cl,3            ; something else?
  1591.     jb    hdsesc3a        ; b = no
  1592.     ja    hdsesc3b        ; a = unknown, ignore
  1593.     mov    al,pixfor+pixbak    ; write both absolute  ESC / 3 d
  1594. hdsesc3a:mov    ccode,al        ; use as pixel op coding
  1595. hdsesc3b:push    prestate        ; get previous state
  1596.     pop    ttstate            ; restore it
  1597.     ret
  1598.  
  1599. hdsesc4:cmp    al,'h'            ; set space, backspace control?
  1600.     je    hdsesc4a        ; e = yes
  1601.     cmp    al,'l'            ; reset space, backspace control?
  1602.     jne    hdsesc9            ; ne = no
  1603.     xor    ah,ah            ; say resetting
  1604.     jmp    short hdsesc5
  1605. hdsesc4a:mov    ah,1            ; say setting
  1606. hdsesc5:cmp    param,2            ; space control?
  1607.     jne    hdsesc5a        ; ne = no
  1608.     mov    spcontrol,ah        ; reset (0) or set destructive SPACE
  1609.     push    prestate        ; get previous state
  1610.     pop    ttstate            ; restore it
  1611.     ret
  1612. hdsesc5a:cmp    param,9            ; destructive backspace?
  1613.     jne    hdsesc13        ; ne = no
  1614.     mov    bscontrol,ah        ; reset (0) or set destructive BS
  1615.  
  1616. hdsesc9:cmp    al,'C'            ; user defined fill pattern #1?
  1617.     jne    hdsesc10        ; ne = no
  1618.     mov    di,offset filpat13    ; storage area for user pattern #1
  1619.     jmp    short hdsesc11
  1620. hdsesc10:cmp    al,'D'            ; user defined fill pattern #2?
  1621.     jne    hdsesc11        ; ne = no
  1622.     mov    di,offset filpat14    ; storage area for user pattern #2
  1623. hdsesc11:mov    cx,8            ; do 8 paramters
  1624.     xor    bx,bx
  1625. hdsesc12:mov    ax,param[bx]        ; copy 8 bit fill pattern
  1626.     mov    [di],al            ; to array
  1627.     add    bx,2
  1628.     inc    di
  1629.     loop    hdsesc12
  1630. hdsesc13:push    prestate        ; get previous state
  1631.     pop    ttstate            ; restore it
  1632.     ret
  1633. hdsesc    endp
  1634.  
  1635. ; Analyze ESC [ Pn ; Pn m  color command    
  1636. ; where Pn = 30-37 foreground color, 40-47 background color, ANSI standard
  1637. ; Enter with escape sequence already parsed.
  1638. TEKCOL    proc    near
  1639.     push    si
  1640.     cld
  1641.     mov    al,gfcol        ; update these in case error
  1642.     mov    tfcol,al
  1643.     mov    al,gbcol
  1644.     mov    tbcol,al
  1645.     mov    si,offset param        ; parameters from parser
  1646.     mov    cx,nparam        ; number of parameters
  1647. tekco1:    jcxz    tekco5            ; z = none left
  1648.     lodsw                ; parameter to ax
  1649.     dec    cx
  1650.     or    ax,ax            ; 0, remove intensity, set b/w?
  1651.     jnz    tekco2            ; nz = no
  1652.     mov    tfcol,7            ; regular white
  1653.     mov    tbcol,0            ;  on black
  1654.     jmp    short tekco1
  1655.  
  1656. tekco2:    cmp    ax,1            ; intensity bit?
  1657.     jne    tekco3            ; ne = no
  1658.     or    tfcol,8            ; set foreground intensity
  1659.     jmp    short tekco1
  1660.     
  1661. tekco3:    cmp    ax,30            ; foreground series?
  1662.     jb    tekco1            ; b = no
  1663.     cmp    ax,37
  1664.     ja    tekco4            ; a = no
  1665.     sub    ax,30            ; remove bias
  1666.     push    bx
  1667.     mov    bl,al
  1668.     xor    bh,bh
  1669.     mov    al,byte ptr colortb[bx]    ; reverse coloring
  1670.     pop    bx
  1671.     and    tfcol,not (7)        ; retain intensity bit
  1672.     or    tfcol,al        ; remember foreground color
  1673.     jmp    short tekco1
  1674.  
  1675. tekco4:    cmp    ax,40
  1676.     jb    tekco1
  1677.     cmp    ax,47            ; legal value?
  1678.     ja    tekco1            ; a = no
  1679.     sub    al,40
  1680.     push    bx
  1681.     mov    bl,al
  1682.     xor    bh,bh
  1683.     mov    al,byte ptr colortb[bx]    ; reverse coloring
  1684.     pop    bx
  1685.     mov    tbcol,al        ; remember background color
  1686.     jmp    short tekco1
  1687.  
  1688. tekco5:    cmp    ninter,0        ; intermediates?
  1689.     jne    tekco7            ; ne = yes, no go
  1690.     cmp    lparam,0        ; letter parameter?
  1691.     jne    tekco7            ; ne = yes, no go
  1692.     cmp    nparam,0        ; number of ansi arguments, zero?
  1693.     ja    tekco6            ; a = no, got some
  1694.     mov    tbcol,0            ; none is same as 0, set b/w
  1695.     mov    tfcol,7
  1696. tekco6:    mov    al,tbcol        ; success, store coloring
  1697.     mov    gbcol,al        ; set background color
  1698.     mov    al,tfcol
  1699.     mov    gfcol,al        ; set foreground color
  1700.     call    fixcolor        ; do special ega corrections
  1701.     mov    al,gfcol        ; update these in case error
  1702.     mov    tfcol,al
  1703.     mov    colpal[7],al        ; foreground goes here
  1704.     mov    al,gbcol
  1705.     mov    tbcol,al
  1706.     mov    colpal[0],al        ; background goes here
  1707. tekco7:    pop    si
  1708.     clc
  1709.     ret
  1710. TEKCOL    endp
  1711.  
  1712. ; Revise screen color codes for ega boards with mono displays and limited
  1713. ; memory.
  1714. fixcolor proc    near
  1715.     cmp    graph_mode,ega        ; one of these ega modes?
  1716.     je    fixcol6            ; e = yes
  1717.     cmp    graph_mode,colorega
  1718.     je    fixcol6
  1719.     cmp    graph_mode,monoega
  1720.     je    fixcol6
  1721.     cmp    plotptr,offset pltcga    ; using CGA style graphics?
  1722.     jne    fixcol5            ; ne = no
  1723.     and    gfcol,7            ; strip intensity
  1724.     jmp    short fixcol6        ; keep colors different
  1725. fixcol5:ret                ; else ignore color corrections
  1726. fixcol6:mov    ah,gfcol
  1727.     mov    al,gbcol
  1728.     cmp    graph_mode,monoega    ; monochrome ega display?
  1729.     jne    fixcol3            ; ne = no
  1730.     test    al,7            ; bright backgound?
  1731.     jnz    fixcol1            ; nz = yes
  1732.     mov    ah,1            ; normal foreground
  1733.     test    gfcol,8            ; intensity on?
  1734.     jz    fixcol1            ; z = no
  1735.     mov    ah,5            ; say bright foreground
  1736. fixcol1:test    al,7            ; black backgound?
  1737.     jz    fixcol2            ; z = yes
  1738.     mov    al,1            ; regular video
  1739. fixcol2:cmp    ah,al            ; same color in both?
  1740.     jne    fixcol3            ; ne = no
  1741.     mov    ah,1            ; make foreground regular
  1742.     xor    al,al            ;  and background black
  1743. fixcol3:mov    gfcol,ah
  1744.     mov    gbcol,al
  1745.     cmp    gpage,0            ; minimal memory (64KB mono and ega)?
  1746.     ja    fixcol4            ; a = no, enough, else strange mapping
  1747.     mov    al,gfcol        ; fix coloring to map planes C0 to C1
  1748.     and    al,5            ; and C2 to C3 (as 0, 3, 0Ch, or 0Fh)
  1749.     mov    ah,al            ; make a copy
  1750.     shl    ah,1            ; duplicate planes C0, C2 in C1, C3
  1751.     or    al,ah            ; merge the bits
  1752.     mov    gfcol,al        ; store proper foreground color
  1753.     mov    al,gbcol        ; repeat for background color
  1754.     and    al,5
  1755.     mov    ah,al
  1756.     shl    ah,1
  1757.     or    al,ah
  1758.     mov    gbcol,al
  1759. fixcol4:ret
  1760. fixcolor endp
  1761.  
  1762. tekrid    proc    near            ; report Tek screen parameters
  1763.     cmp    lparam,'?'        ; possible "ESC [ ? 38 l"?
  1764.     jne    tekridx            ; ne = no
  1765.     cmp    nparam,1        ; just one numeric parameter?
  1766.     jne    tekridx            ; ne = no
  1767.     cmp    param,256        ; correct value?
  1768.     je    tekrid1            ; e = yes
  1769. tekridx:ret
  1770. tekrid1:push    es            ; as ESC [ ? 256; height; len; #col n
  1771.     push    ds
  1772.     pop    es
  1773.     cld
  1774.     mov    di,offset tempname    ; a temp buffer
  1775.     mov    al,escape        ; report
  1776.     stosb
  1777.     mov    al,'['
  1778.     stosb
  1779.     mov    al,'?'
  1780.     stosb
  1781.     mov    ax,256
  1782.     call    dec2di            ; write ascii digits
  1783.     mov    al,';'
  1784.     stosb
  1785.     mov    ax,ybot            ; do height
  1786.     inc    ax
  1787.     cmp    graph_mode,mono        ; pure mono text system?
  1788.     jne    tekrid7a        ; ne = no
  1789.     mov    ax,24
  1790. tekrid7a:call    dec2di
  1791.     mov    al,';'            ; separator
  1792.     stosb
  1793.     mov    ax,xmax            ; width
  1794.     add    ax,8            ; in dots
  1795.     cmp    graph_mode,mono        ; pure mono text system?
  1796.     jne    tekrid7b        ; ne = no
  1797.     mov    ax,80
  1798. tekrid7b:call    dec2di
  1799.     mov    al,';'            ; separator
  1800.     stosb
  1801.     mov    al,'1'            ; screen colors, assume 1
  1802.     stosb
  1803.     cmp    plotptr,offset pltcga    ; using CGA style graphics?
  1804.     je    tekrid4            ; e = yes
  1805.     cmp    graph_mode,monoega    ; monochrome monitor on ega?
  1806.     je    tekrid4            ; e = yes
  1807.     cmp    graph_mode,mono        ; pure mono text system?
  1808.     jne    tekrid3
  1809.     mov    byte ptr [di-1],'0'    ; say zero colors
  1810.     jmp    short tekrid4
  1811. tekrid3:mov    al,'6'
  1812.     stosb                ; say 16
  1813. tekrid4:mov    al,'n'            ; end of string
  1814.     stosb
  1815.     call    outstrng        ; send the string
  1816.     pop    es
  1817.     ret
  1818. tekrid    endp
  1819.  
  1820. tekprpt    proc    near
  1821.     cmp    nparam,1        ; one or more numeric parameters?
  1822.     jb    tekrprx            ; b = no
  1823.     cmp    param,2            ; "CSI 2 $ u"?
  1824.     jne    tekrprx            ; ne = no
  1825.     cmp    inter,'$'        ; correct Intermediate?
  1826.     jne    tekrprx            ; ne = no
  1827.     call    dword ptr rptptr    ; invoke the palette report generator
  1828. tekrprx:ret
  1829. tekprpt    endp
  1830.  
  1831. tekrpt    proc    FAR            ; report VT340 color palette
  1832.     push    es            ; DECRQTSR(request), DECCTR(response)
  1833.     push    ds
  1834.     pop    es
  1835.     push    di
  1836.     push    bx
  1837.     cld
  1838.     mov    di,offset tempname    ; a temp buffer
  1839.     mov    al,escape        ; report
  1840.     stosb
  1841.     cmp    plotptr,offset pltcga    ; using CGA style graphics?
  1842.     je    tekrpt9            ; e = yes
  1843.     cmp    graph_mode,mono        ; pure mono text system?
  1844.     je    tekrpt9            ; e = yes
  1845.     cmp    graph_mode,monoega    ; monochrome monitor on ega?
  1846.     jne    tekrpt10        ; ne = no
  1847. tekrpt9:mov    ax,'0P'            ; b/w systems report DCS 0 $ s ST
  1848.     stosw
  1849.     mov    ax,'s$'
  1850.     stosw
  1851.     call    outstrng
  1852.     jmp    tekrpt8
  1853.  
  1854. tekrpt10:mov    ax,'2P'            ; color systems report DCS 2 $ s...ST
  1855.     stosw
  1856.     mov    ax,'s$'
  1857.     stosw                ; "ESC [ 2 $ s"
  1858.     call    outstrng        ; output this string
  1859.     mov    cx,16            ; number of palette registers to do
  1860.     xor    bx,bx            ; begin with color palette 0
  1861. tekrpt1:push    bx            ; save palette index
  1862.     push    cx            ; save loop counter
  1863.     mov    di,offset tempname    ; buffer
  1864.     mov    ax,bx            ; palette number
  1865.     call    dec2di            ; palette register, to buffer
  1866.     mov    ax,'2;'            ; ";2;" means sending RGB values
  1867.     stosw
  1868.     mov    al,';'
  1869.     stosb
  1870.     mov    ah,colpal[bx]        ; get palette iRGB
  1871.     mov    al,rgbbold/4        ; assume dark red for bold black
  1872.     cmp    ah,8            ; bold black?
  1873.     je    tekrpt2            ; e = yes
  1874.     xor    al,al
  1875.     test    ah,4            ; red?
  1876.     jz    tekrpt2            ; z = no
  1877.     mov    al,rgbbold/2        ; say red, 40%
  1878.     test    ah,8            ; bold?
  1879.     jz    tekrpt2            ; z = no
  1880.     mov    al,rgbbold        ; more if bold
  1881. tekrpt2:push    ax
  1882.     xor    ah,ah            ; clear high byte
  1883.     call    dec2di            ; store red
  1884.     pop    ax
  1885.     mov    al,';'            ; separator
  1886.     stosb
  1887.     mov    al,rgbbold/4        ; assume dark green for bold black
  1888.     cmp    ah,8            ; bold black?
  1889.     je    tekrpt4            ; e = yes
  1890.     xor    al,al
  1891.     test    ah,2            ; green?
  1892.     jz    tekrpt4            ; z = no
  1893.     mov    al,rgbbold/2        ; say green, 40%
  1894.     test    ah,8            ; bold?
  1895.     jz    tekrpt4            ; z = no
  1896.     mov    al,rgbbold        ; more if bold
  1897. tekrpt4:push    ax
  1898.     xor    ah,ah            ; clear high byte
  1899.     call    dec2di            ; store green
  1900.     pop    ax
  1901.     mov    al,';'            ; separator
  1902.     stosb
  1903.     mov    al,rgbbold/4        ; assume dark blue for bold black
  1904.     cmp    ah,8            ; bold black?
  1905.     je    tekrpt6            ; e = yes
  1906.     xor    al,al
  1907.     test    ah,1            ; blue?
  1908.     jz    tekrpt6            ; z = no
  1909.     mov    al,rgbbold/2        ; say blue, 40%
  1910.     test    ah,8            ; bold?
  1911.     jz    tekrpt6            ; z = no
  1912.     mov    al,rgbbold        ; more if bold
  1913. tekrpt6:xor    ah,ah            ; clear high byte
  1914.     call    dec2di            ; store blue
  1915.     pop    cx            ; recover loop counter
  1916.     cmp    cx,1            ; doing last item?
  1917.     je    tekrpt7            ; e = yes, do not send another "/"
  1918.     mov    al,'/'            ; separator
  1919.     stosb
  1920. tekrpt7:push    cx
  1921.     call    outstrng        ; output this string
  1922.     pop    cx
  1923.     pop    bx            ; recover palette index
  1924.     inc    bx            ; ready for next palette
  1925.     dec    cx
  1926.     jz    tekrpt8            ; z = done
  1927.     jmp    tekrpt1            ; do all palettes
  1928. tekrpt8:mov    al,escape        ; DCS terminator ST
  1929.     call    outmodem
  1930.     mov    al,'\'
  1931.     call    outmodem
  1932.     pop    bx
  1933.     pop    di
  1934.     pop    es
  1935.     ret
  1936. tekrpt    endp
  1937.  
  1938. ; Output string in tempname. Enter with di pointing at last byte+1. Return
  1939. ; with di at the same place.
  1940. outstrng proc    near
  1941.     mov    ttyact,0        ; group output for network
  1942.     push    cx
  1943.     mov    cx,di            ; compute length
  1944.     mov    di,offset tempname    ; start of buffer
  1945.     sub    cx,di            ; start of buffer
  1946.     jle    outstn3            ; le = nothing to do
  1947. outstn1:mov    al,[di]
  1948.     inc    di
  1949.     cmp    cx,1            ; last character?
  1950.     ja    outstn2            ; a = no
  1951.     mov    ttyact,1        ; end group output for network
  1952. outstn2:call    outmodem        ; send the byte
  1953.     loop    outstn1            ; do the string
  1954. outstn3:pop    cx
  1955.     ret
  1956. outstrng endp
  1957.  
  1958. ; Process Device Control Strings (DCS or ESC P lead-in chars, parameters,
  1959. ; and Final character already read). Prepare to gather strings.
  1960. tekdcs    proc    near
  1961.     mov    dcsstrf,al        ; record Final char
  1962.     mov    emubufc,0        ; clear string count
  1963.     mov    cx,maxparam        ; number of DCS parameters
  1964.     push    si            ; copy these to the DCS area so that
  1965.     push    di            ;  they are not lost when an ST is
  1966.     push    es            ;  parsed (parser clears ESC items)
  1967.     push    ds
  1968.     pop    es
  1969.     mov    si,offset param        ; ESC paramater storage area, numeric
  1970.     mov    di,offset dparam    ; DCS parameter storage area, numeric
  1971.     cld
  1972.     rep    movsw            ; copy set to DCS storage area
  1973.     mov    cl,lparam         ; copy letter Paramter
  1974.     mov    dlparam,cl
  1975.     mov    cx,maxinter        ; number of intermediate characters
  1976.     mov    si,offset inter        ; source
  1977.     mov    di,offset dinter    ; destination
  1978.     rep    movsb
  1979.     mov    si,nparam        ; number of parameters
  1980.     mov    dnparam,si
  1981.     mov    si,ninter
  1982.     mov    dninter,si        ; number of intermediates
  1983.     pop    es
  1984.     pop    di
  1985.     pop    si
  1986.     cmp    dcsstrf,'q'        ; Sixel Graphics?
  1987.     jne    tekdcs3            ; ne = no
  1988.     mov    ttstate,offset tekgets    ; get string as next state
  1989.     mov    al,chcontrol        ; opaque/transparent char writing
  1990.     or    al,al            ; is it being set?
  1991.     jz    tekdcs2            ; z = no, do not force condition
  1992.     mov    bscontrol,al        ; set destructive BS control
  1993.     mov    spcontrol,al        ; set destructive SPACE control
  1994. tekdcs2:ret
  1995. tekdcs3:cmp    dcsstrf,'p'        ; restore color palette (DCS 2 $ p)?
  1996.     jne    tekdcs1            ; ne = no
  1997.     cmp    nparam,1        ; just one parameter?
  1998.     jne    tekdcs1            ; ne = no
  1999.     cmp    param,2            ; correct parameter?
  2000.     jne    tekdcs1            ; ne = no
  2001.     cmp    dinter,'$'        ; correct intermediate?
  2002.     jne    tekdcs1            ; ne = no
  2003.     mov    ttstate,offset tekrcol    ; get color report as next state
  2004.     ret
  2005. tekdcs1:mov    ttstate,offset tekdcsnul ; consume unknown DCS
  2006.     ret
  2007. tekdcs    endp
  2008.  
  2009. ; Read and discard OSC (ESC ]), PM (ESC ^), APC (ESC _) control sequences
  2010. ; through final ST (ESC \) terminator.
  2011. tekdcsnul proc    near
  2012.     mov    dcsstrf,0        ; simulate a null (dummy) Final char
  2013.     cmp    al,20h            ; control char?
  2014.     jae    tekdcsnu1        ; ae = no, skip
  2015.     jmp    tekctl            ; do control char
  2016. tekdcsnu1:ret
  2017. tekdcsnul endp
  2018.  
  2019. ; State machine to process DCS strings of type "p" (restore color palette)
  2020. ; Enter with "p" char in AL. Callable from outside this file via tekrpal.
  2021. tekrcol    proc    near
  2022.     mov    ttstate,offset tekrco1    ; next state is get parameter
  2023.     push    ax            ; save character
  2024.     push    es
  2025.     push    ds
  2026.     pop    es
  2027.     push    di
  2028.     mov    cx,5            ; five words
  2029.     xor    ax,ax
  2030.     mov    di,offset param        ; clear parameters Pc,Pu,Px,Py,Pz
  2031.     cld
  2032.     rep    stosw
  2033.     pop    di
  2034.     pop    es
  2035.     mov    nparam,0        ; work on initial parameter first
  2036.     pop    ax
  2037. tekrco1:cmp    al,escape        ; escape, as in ESC \?
  2038.     je    tekrcost        ; e = yes, finish command
  2039.     cmp    al,' '            ; control code?
  2040.     jb    tekrco5            ; b = yes, ignore it
  2041.     push    bx
  2042.     mov    bx,nparam        ; parameter number
  2043.     shl    bx,1            ; make it a word index
  2044.     mov    cx,param[bx]        ; accumulated parameter
  2045.     call    getdec            ; accumulate decimal value
  2046.     mov    param[bx],cx        ; remember accumulation
  2047.     pop    bx
  2048.     jnc    tekrco5            ; nc = got a digit char
  2049.     inc    nparam            ; say have another complete parameter
  2050.     cmp    al,'/'            ; this kind of separator?
  2051.     je    tekrco3            ; e = yes, finish
  2052.     cmp    al,';'            ; break char is separator?
  2053.     jne    tekrco4            ; ne = no, decode current sequence
  2054. tekrco3:cmp    nparam,5        ; have 5 params already?
  2055.     jb    tekrco5            ; n = no, continue reading
  2056. tekrco4:call    tekgco4            ; process parameters in msgibm file
  2057.     mov    ttstate,offset tekrcol    ; next state is get parameter
  2058. tekrco5:ret                ; start over on next field
  2059.  
  2060. tekrcost:                ; get here on ST
  2061.     cmp    nparam,5        ; enough parameters to finish cmd?
  2062.     jb    tekrcos1        ; b = no, abandon it
  2063.     call    tekgco4            ; update from last data item
  2064.     mov    al,escape
  2065. tekrcos1:jmp    tekctl
  2066. tekrcol    endp
  2067.  
  2068. ; State machine to process DCS strings of type "q" (Sixel Command and Data)
  2069. ; Enter with new char in AL.
  2070. tekgets    proc    near
  2071.     mov    ttstate,offset tekgets    ; set state to ourselves
  2072.     mov    nparam,0        ; say no pending control sequences
  2073.     cmp    al,20h            ; control character?
  2074.     jae    tekgsch            ; ae = no, analyze
  2075.     jmp    tekctl            ; do control char
  2076.                     ; single sixel char state
  2077. tekgsch:cmp    al,3fh            ; legal sixel data char?
  2078.     jb    tekgrpt            ; b = no, try repeated char
  2079.     mov    cx,1            ; repeat count of 1
  2080.     jmp    sixplt            ; plot the six dots
  2081.  
  2082. tekgrpt:cmp    al,'!'            ; repeated char?
  2083.     jne    tekgera            ; ne = no
  2084.     mov    ttstate,offset tekgrpt0    ; next state is get repeat parameter
  2085.     mov    param,0
  2086.     mov    nparam,0
  2087.     ret
  2088.  
  2089. tekgrpt0:cmp    al,' '            ; control char?
  2090.     jae    tekgrpt1        ; ae = no
  2091.     jmp    tekctl            ; process control char
  2092. tekgrpt1:mov    cx,param        ; first param is used here
  2093.     call    getdec            ; accumulate repeat count to cx
  2094.     mov    param,cx        ; retain current count
  2095.     jc    tekgrpt2        ; c = ended on non-numeric
  2096.     ret                ; get more characters
  2097. tekgrpt2:cmp    al,3fh            ; break char, is it a sixel datum?
  2098.     jb    tekgrpt3        ; b = no, it is illegal, quit
  2099.     call    sixplt            ; plot cx versions of the six bits
  2100.     mov    ttstate,offset tekgets    ; return to sixel idle state
  2101.     ret
  2102. tekgrpt3:jmp    short tekgets        ; reprocess break character
  2103.  
  2104. tekgera:cmp    al,22h            ; double quote raster attribute?
  2105.     jne    tekgco            ; ne = no, try color
  2106.     mov    param,0            ; clear parameters, Pan
  2107.     mov    param[2],0        ; Pad
  2108.     mov    param[4],0        ; Ph
  2109.     mov    param[6],0        ; Pv
  2110.     mov    nparam,0        ; work on initial parameter first
  2111.     mov    ttstate,offset tekgra1    ; next state is get parameter
  2112.     ret
  2113. tekgra1:cmp    al,' '            ; control char?
  2114.     jb    tekgra2            ; b = yes, finish this work first
  2115.     push    bx
  2116.     mov    bx,nparam        ; parameter number
  2117.     shl    bx,1            ; make it a word index
  2118.     mov    cx,param[bx]        ; accumulated parameter
  2119.     call    getdec            ; accumulate decimal value into cx
  2120.     mov    param[bx],cx        ; remember accumulation
  2121.     pop    bx
  2122.     jc    tekgra2            ; c = failure to get a digit char
  2123.     ret
  2124. tekgra2:inc    nparam            ; say have another complete parameter
  2125.     cmp    nparam,4        ; got all four params Pan,Pad,Ph,Pv?
  2126.     je    tekgra4            ; e = yes
  2127.     cmp    al,';'            ; break char is separator?
  2128.     jne    tekgra3            ; ne = no, quit now
  2129.     ret                ; get more characters
  2130. tekgra3:jmp    tekgets            ; restart with the break char
  2131.  
  2132. tekgra4:;;; perform raster attributes work here
  2133.     mov    ttstate,offset tekgets
  2134.     ret
  2135.  
  2136. tekgco:    cmp    al,'#'            ; color introducer?
  2137.     je    tekgco0            ; e = yes
  2138.     jmp    tekgcr            ; ne = no
  2139. tekgco0:mov    ttstate,offset tekgco1    ; next state is get parameter
  2140.     push    ds
  2141.     pop    es
  2142.     push    di
  2143.     mov    cx,5            ; five words
  2144.     xor    ax,ax
  2145.     mov    di,offset param        ; clear parameters Pc,Pu,Px,Py,Pz
  2146.     cld
  2147.     rep    stosw
  2148.     pop    di
  2149.     pop    es
  2150.     mov    nparam,0        ; work on initial parameter first
  2151.     ret
  2152. tekgco1:cmp    al,' '            ; control char?
  2153.     jb    tekgco2            ; b = yes, finish this work first
  2154.     push    bx
  2155.     mov    bx,nparam        ; parameter number
  2156.     shl    bx,1            ; make it a word index
  2157.     mov    cx,param[bx]        ; accumulated parameter
  2158.     call    getdec            ; accumulate decimal value
  2159.     mov    param[bx],cx        ; remember accumulation
  2160.     pop    bx
  2161.     jc    tekgco2            ; c = failure to get a digit char
  2162.     ret
  2163. tekgco2:inc    nparam            ; say have another complete parameter
  2164.     cmp    al,';'            ; break char is separator?
  2165.     jne    tekgco3            ; ne = no, decode current sequence
  2166.     cmp    nparam,5        ; have 5 params already?
  2167.     jae    tekgco3            ; ae = yes, process them now
  2168.     ret                ;  else get more parameters
  2169. tekgco3:cmp    nparam,1        ; just one parameter?
  2170.     je    tekgco3a        ; e = yes, select from palette
  2171.     jb    tekgco3b        ; b = none, reprocess as sixel
  2172.     call    tekgco4            ; process parameters
  2173.     mov    nparam,0        ; clear parameters
  2174.     jmp    tekgets            ; reprocess char as sixel
  2175.  
  2176. tekgco3a:push    bx            ; select color from palette
  2177.     mov    bx,param[0]        ; get color number
  2178.     xor    bh,bh            ; make 0-255
  2179.     mov    bl,colpal[bx]        ; get color from palette
  2180.     mov    gfcol,bl        ; set active foreground color
  2181.     pop    bx
  2182.     push    ax            ; save char in al
  2183.     call    fixcolor        ; fix color too, if req'd
  2184.     pop    ax
  2185. tekgco3b:mov    nparam,0        ; clear parameters
  2186.     jmp    tekgets            ; reprocess char as sixel
  2187.  
  2188.                     ; set IRGB/HLS color to color palette
  2189. tekgco4:cmp    param[2],2        ; Pu (1-2), wanted RBG?
  2190.     je    tekgco4b        ; e = yes
  2191.     cmp    param[2],1        ; Pu, wanted HLS?
  2192.     jne    tekgco4a        ; ne = no
  2193.     jmp    tekgco9            ; do HLS scheme
  2194. tekgco4a:mov    nparam,0        ; clear parameters
  2195.     ret                ; return without doing work
  2196. tekgco4b:push    ax            ; iRGB, save break char in al
  2197.     mov    ax,param[4]        ; red
  2198.     mov    bx,param[6]        ; green
  2199.     mov    dx,param[8]        ; blue
  2200.     xor    cx,cx            ; cl has final color index, 0-15
  2201.     or    ch,al
  2202.     or    ch,bl
  2203.     or    ch,dl            ; any color?
  2204.     jcxz    tekgco7            ; z = no, use cl = 0 black
  2205.     cmp    ax,rgbbold        ; setting red bold?
  2206.     jae    tekgco4c        ; ae = yes
  2207.     cmp    bx,rgbbold        ; setting green bold?
  2208.     jae    tekgco4c        ; ae = yes
  2209.     cmp    dx,rgbbold        ; setting blue bold?
  2210.     jb    tekgco4d        ; b = no
  2211. tekgco4c:mov    cl,8            ; set the bold bit
  2212.     jmp    tekgco4e        ; do hues
  2213. tekgco4d:cmp    ax,rgbbold/2        ; all in dim intensities?
  2214.     jae    tekgco4e        ; ae = no
  2215.     cmp    bx,rgbbold/2        ; green?
  2216.     jae    tekgco4e        ; ae = no
  2217.     cmp    dx,rgbbold/2        ; blue
  2218.     jae    tekgco4e        ; ae = no
  2219.     mov    cl,8            ; use bold black (dark grey)
  2220.     jmp    tekgco7
  2221. tekgco4e:or    ax,ax            ; Hues, any red?
  2222.     jz    tekgco5            ; z = no
  2223.     or    cl,4            ; set red bit
  2224.     cmp    ax,rgbbold/2        ; dim?
  2225.     jae    tekgco5            ; ae = no
  2226.     test    cl,8            ; doing bold?
  2227.     jz    tekgco5            ; z = no
  2228.     xor    cl,4            ; clear dim red
  2229. tekgco5:or    bx,bx            ; any green?
  2230.     jz    tekgco6            ; z = no
  2231.     or    cl,2            ; set green bit
  2232.     cmp    bx,rgbbold/2        ; dim?
  2233.     jae    tekgco6            ; ae = no
  2234.     test    cl,8            ; doing bold?
  2235.     jz    tekgco6            ; z = no
  2236.     xor    cl,2            ; clear dim green
  2237. tekgco6:or    dx,dx            ; any blue?
  2238.     jz    tekgco7            ; z = no
  2239.     or    cl,1            ; set blue bit
  2240.     cmp    dx,rgbbold/2        ; dim?
  2241.     jae    tekgco7            ; ae = no
  2242.     test    cl,8            ; doing bold?
  2243.     jz    tekgco7            ; z = no
  2244.     xor    cl,1            ; clear dim blue
  2245. tekgco7:push    bx
  2246.     mov    bx,param[0]        ; Pc, color palette being defined
  2247.     xor    bh,bh            ; make 0-255
  2248.     mov    colpal[bx],cl        ; store color code in palette
  2249.     pop    bx
  2250.     mov    nparam,0        ; say done with this sequence
  2251.     pop    ax            ; recover break char in al
  2252.     ret
  2253.  
  2254.                     ; Hue, Lightness, Saturation
  2255. tekgco9:push    ax            ; save break char
  2256.     xor    cl,cl            ; assummed color of black
  2257.     mov    ax,param[4]        ; Px, Hue, 60 degree slices
  2258.     push    cx
  2259.     mov    cx,360            ; do modulo 360
  2260.     xor    dx,dx            ; clear high order numerator
  2261.     div    cx            ; dx has remainder
  2262.     pop    cx
  2263.     mov    ax,dx            ; put remainder in ax
  2264.     cmp    ax,30            ; blue?
  2265.     jae    tekgco10        ; ae = no
  2266.     or    cl,1            ; blue
  2267.     jmp    short tekgco15
  2268. tekgco10:cmp    ax,90            ; magenta?
  2269.     jae    tekgco11        ; ae = no
  2270.     or    cl,1+4            ; magenta = blue + red
  2271.     jmp    short tekgco15
  2272. tekgco11:cmp    ax,150            ; red?
  2273.     jae    tekgco12        ; ae = no
  2274.     or    cl,4            ; red
  2275.     jmp    short tekgco15
  2276. tekgco12:cmp    ax,210            ; yellow?
  2277.     jae    tekgco13        ; ae = no
  2278.     or    cl,4+2            ; yellow = reg + green
  2279.     jmp    short tekgco15
  2280. tekgco13:cmp    ax,270            ; cyan?
  2281.     jae    tekgco14        ; ae = no
  2282.     or    cl,2+1            ; cyan = green+blue
  2283.     jmp    short tekgco15
  2284. tekgco14:or    cl,1            ; blue
  2285.  
  2286. tekgco15:mov    ax,param[6]        ; Py, Lightness
  2287.     mov    dx,param[8]        ; Pz, Saturation
  2288.     cmp    ax,86            ; lightness is max?
  2289.     jb    tekgco16        ; b = no
  2290.     mov    cl,0fh            ; greater than 85% means bold white
  2291.     jmp    short tekgco22
  2292. tekgco16:cmp    ax,71            ; high lightness?
  2293.     jb    tekgco17        ; b = not that light
  2294.     or    cl,8            ; turn on bold bit
  2295.     cmp    dx,51            ; saturated?
  2296.     jae    tekgco22        ; ae = yes
  2297.     mov    cl,0fh            ; low saturation yields bold white
  2298.     jmp    short tekgco22
  2299. tekgco17:cmp    ax,57            ; central coloring, upper?
  2300.     jb    tekgco18        ; b = no
  2301.     or    cl,8            ; turn on bold bit
  2302.     cmp    dx,51            ; saturated?
  2303.     jae    tekgco22        ; ae = yes, use bold colors
  2304.     mov    cl,7            ; s < 50 is dim white
  2305.     cmp    dx,11            ; saturated less than 11%
  2306.     jae    tekgco22        ; ae = no
  2307.     xor    cl,cl            ; s < 11 is black here
  2308.     jmp    short tekgco22
  2309. tekgco18:cmp    ax,43            ; dim colors, upper?
  2310.     jb    tekgco19        ; b = no
  2311.     or    cl,8            ; turn on bold bit
  2312.     cmp    dx,51            ; saturated?
  2313.     jae    tekgco22        ; ae = yes, use bold colors
  2314.     and    cl,not 8        ; use dim colors
  2315.     jmp    short tekgco22
  2316. tekgco19:cmp    ax,29            ; dim colors, lower?
  2317.     jb    tekgco20        ; b = no
  2318.     cmp    dx,51            ; saturated?
  2319.     jae    tekgco22        ; ae = yes
  2320.     mov    cl,7            ; use dim white
  2321.     jmp    short tekgco22
  2322. tekgco20:cmp    ax,14            ; dark colors?
  2323.     jb    tekgco21        ; b = no
  2324.     cmp    dx,51            ; saturated?
  2325.     jae    tekgco22        ; ae = yes
  2326. tekgco21:xor    cl,cl            ; use black
  2327. tekgco22:push    bx
  2328.     mov    bx,param[0]        ; Pc, color palette being defined
  2329.     xor    bh,bh            ; get palette 0-255
  2330.     mov    colpal[bx],cl        ; store color code in palette
  2331.     pop    bx
  2332.     mov    nparam,0        ; say done with this sequence
  2333.     pop    ax            ; recover break char
  2334.     ret
  2335.  
  2336. tekgcr:    cmp    al,'$'            ; graphics carriage return?
  2337.     jne    tekgnl            ; ne = no
  2338.     mov    x_coord,0        ; go to left margin, no line feed
  2339.     ret
  2340. tekgnl:    cmp    al,'-'            ; graphics new line?
  2341.     jne    tekgunk            ; ne = no
  2342.     mov    x_coord,0        ; go to left margin, no line feed
  2343.     mov    ax,y_coord        ; bottom of char cell
  2344.     add    ax,6            ; go down 6 dots
  2345.     cmp    ax,ybot            ; wrapping below bottom?
  2346.     jbe    tekgnl1            ; be = no
  2347.     mov    ax,ybot            ; stop at bottom (leaves 2 dots free!)
  2348. tekgnl1:mov    y_coord,ax
  2349.     ret
  2350. tekgunk:mov    ttstate,offset tekgets    ; unknown char
  2351.     cmp    al,' '            ; control char?
  2352.     jae    tekgun1            ; ae = no
  2353.     jmp    tektxt            ; process control char
  2354. tekgun1:ret                ; ignore the unknown char
  2355. tekgets    endp
  2356.  
  2357. ; Accumulate decimal value in CX using ascii char in al.
  2358. ; Return with value in CX. Return carry clear if ended on a digit,
  2359. ; return carry set and ascii char in al if ended on a non-digit.
  2360. getdec    proc    near
  2361.     cmp    al,'0'            ; a number?
  2362.     jb    getdecx            ; b = no, quit
  2363.     cmp    al,'9'
  2364.     ja    getdecx            ; a = not a number, quit
  2365.     sub    al,'0'            ; remove ascii bias
  2366.     xchg    cx,ax            ; put char in cx, decimal value in ax
  2367.     push    dx            ; save reg
  2368.     mul    ten            ; times ten for a new digit
  2369.     pop    dx            ; recover reg, ignore overflow
  2370.     add    al,cl            ; add current digit
  2371.     adc    ah,0            ; 16 bits worth
  2372.     xchg    ax,cx            ; rpt cnt back to cx
  2373.     clc                ; say found a digit
  2374.     ret
  2375. getdecx:stc                ; say non-digit (in al)
  2376.     ret
  2377. getdec    endp
  2378.  
  2379. ; Display lower six bits of AL in a column, a sixel datum. Do CX times.
  2380. ; Location is PC text cursor, x_coord, y_coord, with least significant bit
  2381. ; at the top (at y_coord-8). Increments x_coord by one for each interation
  2382. ; but stops at right margin and does not change y_coord. If dparam[2], P2,
  2383. ; is 1 then color pattern 0 bits in current background, else skip them.
  2384. sixplt    proc    near
  2385.     or    cx,cx            ; repeat count present?
  2386.     jnz    sixplt1            ; nz = yes
  2387.     ret
  2388. sixplt1:push    ax
  2389.     push    bx
  2390.     push    linepat            ; save line pattern
  2391.     sub    al,3fh            ; remove ascii bias from sixel char
  2392.     xor    ah,ah
  2393.     mov    linepat,ax        ; our dot pattern in lower 6 bits
  2394.     mov    di,y_coord        ; text bottom cell line
  2395.     sub    di,8            ; go to top of 8 high char cell
  2396.     jnc    sixplt2            ; nc = no wrap over top
  2397.     xor    di,di            ; limit to screen top
  2398. sixplt2:mov    bx,di            ; bx = ending y
  2399.     add    bx,5            ; plus our six dots (goes down screen)
  2400.     cmp    bx,ybot            ; wrapping below bottom?
  2401.     jbe    sixplt3            ; be = no
  2402.     mov    bx,ybot            ; stop at bottom
  2403. sixplt3:mov    ax,x_coord        ; left edge of text cell
  2404.     mov    si,ax            ; si=starting, ax=ending PC x coord
  2405.     add    xmax,7            ; refer to right edge, not right char
  2406.     push    es            ; set up for dot plotting, save regs
  2407.     push    si
  2408.     push    di
  2409.     push    dx
  2410.     push    bp
  2411.     mov    dl,ccode        ; existing pixel op code
  2412.     push    dx            ; save ccode around line drawing
  2413.     mov    ccode,pixor        ; set OR pixel op for use by plot()
  2414.     cmp    gfcol,0            ; all black dots?
  2415.     jne    sixplt3a        ; ne = no
  2416.     mov    ccode,pixfor        ; yes, force overwriting to nulls
  2417. sixplt3a:push    cx
  2418.     call    psetup            ; setup display and es:di and es:si
  2419.     pop    cx
  2420.                     ; start sixel repeat loop
  2421. sixplt4:push    cx            ; save sixel repeat count
  2422.     push    di            ; save y starting screen address
  2423.     mov    bp,linepat        ; store active line pattern word in BP
  2424.     mov    cx,6            ; six dots per sixel
  2425.                     ; start six dot loop
  2426. sixplt5:push    cx            ; save dot count
  2427.     mov    cl,pixFor        ; assume foreground coloring
  2428.     test    bp,1            ; bit to be plotted, is it a 1?
  2429.     jnz    sixplt6            ; nz = yes, plot in foreground color
  2430.     cmp    dparam[2],1        ; P2 = 1, skip over 0's?
  2431.     je    sixplt6            ; e = yes
  2432.     mov    cl,pixbak        ; use background write pixel op
  2433.     or    bp,1            ; set pattern bit so we see a pixel
  2434. sixplt6:mov    ccode,cl        ; desired pixel op
  2435.     call    plotptr            ; plot a dot if it is a 1
  2436.     call    pincy            ; next dot down the screen (di)
  2437.     pop    cx            ; recover dot counter
  2438.     loop    sixplt5            ; do each of 6 dots
  2439.                     ;
  2440.     pop    di            ; recover starting y screen coord
  2441.     pop    cx            ; recover repeat count
  2442.     cmp    ax,xmax            ; off right edge?
  2443.     jae    sixplt8            ; ae = yes
  2444.     inc    ax            ; move right one pixel
  2445.     inc    si            ; start and stop x's
  2446. sixplt8:loop    sixplt4            ; repeat sixel cx times
  2447.     pop    dx
  2448.     mov    ccode,dl        ; recover main color code
  2449.     pop    bp
  2450.     pop    dx
  2451.     pop    di
  2452.     pop    si
  2453.     pop    es
  2454.     mov    x_coord,ax        ; new text starting x coord
  2455.     sub    xmax,7            ; restore to right most char cell
  2456.     pop    linepat            ; restore normal line pattern
  2457.     pop    bx
  2458.     pop    ax
  2459.     ret
  2460. sixplt    endp
  2461.  
  2462. ; Process ST or ESC \  String Terminator.
  2463. tekgotst proc    near
  2464.     mov    dcsstrf,0        ; clear DCS Final char
  2465.     mov    nparam,0
  2466.     mov    ninter,0
  2467.     mov    al,colpal[7]        ; reset foreground to palette 7
  2468.     mov    gfcol,al
  2469.     mov    al,colpal[0]        ; and background to palette 0
  2470.     mov    gbcol,al
  2471.     call    fixcolor        ; and fix up coloring, if req'd
  2472.     mov    prestate,offset tektxt    ; reset state of emulator to normal
  2473.     mov    ttstate,offset tektxt
  2474.     call    setcursor        ; restore text cursor
  2475.     ret
  2476. tekgotst endp
  2477.  
  2478. TEKLINE    proc    near            ; GS line drawing
  2479.     cmp    al,' '            ; control char?
  2480.     jae    teklin3            ; ae = no
  2481.     cmp    al,CR            ; exit drawing on CR,LF,RS,US,FS,CAN
  2482.     je    teklin2            ; e = yes, a cr
  2483.     cmp    al,LF            ; these terminate line drawing cmds
  2484.     je    teklin2
  2485.     cmp    al,FS            ; <FS>
  2486.     je    teklin2
  2487.     cmp    al,GS            ; <GS>
  2488.     je    teklin2
  2489.     cmp    al,RS            ; <RS>
  2490.     je    teklin2
  2491.     cmp    al,US            ; <US>
  2492.     je    teklin2
  2493.     cmp    al,CAN            ; and <CAN>
  2494.     je    teklin2            ; BUT ignore other control chars
  2495.     cmp    al,escape        ; escape?
  2496.     je    teklin1            ; e = yes, come back to this state
  2497.     ret                ; ignore stray control char
  2498. teklin1:jmp    tekctl            ; process control char
  2499. teklin2:mov    lastc,0            ; clear last drawing coordinate flag
  2500.     mov    visible,0        ; invisible again
  2501.     jmp    tektxt            ; process char under text mode
  2502.  
  2503. teklin3:call    tekxyc            ; parse coordinates from input bytes
  2504.     jc    teklin4            ; c = done, do the plotting
  2505.     ret                ; nc = not done yet
  2506. teklin4:mov    cl,visible        ; get moveto or drawto variable
  2507.     call    tekdraw            ; move that point
  2508.     mov    visible,1        ; say next time we draw
  2509.     ret
  2510. TEKLINE    endp
  2511.     
  2512. TEKPNT    proc    near            ; FS plot single point
  2513.     cmp    al,' '            ; control char?
  2514.     jae    tekpnt3            ; ae = no
  2515.     cmp    al,CR            ; exit drawing on CR,LF,RS,US,FS,CAN
  2516.     je    tekpnt2            ; e = yes, a cr
  2517.     cmp    al,LF             ; these terminate line drawing cmds
  2518.     je    tekpnt2
  2519.     cmp    al,FS            ; <FS>
  2520.     je    tekpnt2
  2521.     cmp    al,GS            ; <GS>
  2522.     je    tekpnt2
  2523.     cmp    al,RS            ; <RS>
  2524.     je    tekpnt2
  2525.     cmp    al,US            ; <US>
  2526.     je    tekpnt2
  2527.     cmp    al,CAN            ; and <CAN>
  2528.     je    tekpnt2            ; BUT ignore other control chars
  2529.     cmp    al,escape        ; escape?
  2530.     je    tekpnt1            ; e = yes
  2531.     clc
  2532.     ret                ; ignore stray control char
  2533. tekpnt1:jmp    tekctl            ; process control char
  2534. tekpnt2:mov    lastc,0            ; clear last drawing coordinate flag
  2535.     mov    visible,0        ; invisible again
  2536.     jmp    tektxt            ; process char under text mode
  2537.  
  2538. tekpnt3:call    tekxyc            ; parse coordinates
  2539.     jc    tekpnt4            ; c = done, do the plotting
  2540.     ret                ; nc = not done yet
  2541. tekpnt4:xor    cl,cl            ; do not draw
  2542.     call    tekdraw            ; move to the point
  2543.     mov    ax,si            ; copy starting point to end point
  2544.     mov    bx,di            ; ax,bx,si,di are in PC coordinates
  2545.     mov    cl,1            ; make plot visible
  2546.     call    line            ; draw the dot
  2547.     mov    visible,0        ; return to invisibility
  2548.     clc
  2549.     ret
  2550. TEKPNT    endp
  2551.  
  2552. ; Decode graphics x,y components. Returns carry set to say have all
  2553. ; components for a line, else carry clear. Understands 4014 lsb extensions.
  2554. ; Permits embedded escape sequences.
  2555. TEKXYC    proc    near
  2556.     cmp    al,40h
  2557.     jb    tekgh2            ; 20-3F are HIX or HIY
  2558.     cmp    al,60h            ; 40-5F are LOX (causes beam movement)
  2559.     jb    tekgh4            ; 60-7F are LOY
  2560.                     ; extract low-order 5 bits of Y coord
  2561.     mov    ah,tek_loy        ; copy previous LOY to MSB (4014)
  2562.     mov    tek_lsb,ah
  2563.     and    al,1Fh            ; LOY is 5 bits
  2564.     mov    tek_loy,al
  2565.     cmp    lastc,loy        ; 2nd LOY in a row?
  2566.     je    tekgh1            ; e = yes, then LSB is valid
  2567.     mov    tek_lsb,0        ; 1st one, clear LSB
  2568. tekgh1:    mov    lastc,loy        ; LOY seen, expect HIX (instead of HIY)
  2569. tekgh0:    clc                ; c clear = not completed yet
  2570.     ret
  2571. tekghx:    mov    ttstate,offset tektxt    ; go to TEKTXT next time
  2572.     mov    lastc,0            ; clear last drawing coordinate flag
  2573.     or    status,txtmode        ; set text mode in status byte
  2574.     clc                ; carry clear means done
  2575.     ret
  2576.  
  2577.         ; Extract high-order 5 bits (X or Y, depending on lastc)
  2578. tekgh2: and    ax,1Fh            ; just 5 bits
  2579.     mov    cl,5
  2580.     shl    ax,cl            ; shift over 5 bits
  2581.     cmp    lastc,loy        ; was last coordinate a low-y?
  2582.     je    tekgh3            ; e = yes, parse hix
  2583.     mov    tek_hiy,ax        ; this byte has HIY
  2584.     mov    lastc,hiy
  2585.     clc
  2586.     ret
  2587. tekgh3: mov    tek_hix,ax        ; this byte has HIX
  2588.     mov    lastc,hix
  2589.     clc
  2590.     ret
  2591. tekgh4: and    al,1Fh            ; just 5 bits
  2592.     mov    tek_lox,al
  2593.     mov    lastc,lox
  2594.     mov    ax,tek_hix        ; combine HIX*32
  2595.     or    al,tek_lox        ;  with LOX
  2596.     mov    bx,tek_hiy        ; same for Y
  2597.     or    bl,tek_loy
  2598.     stc                ; set c to say completed operation
  2599.     ret
  2600. TEKXYC    endp
  2601.  
  2602. TEKRLIN    proc    near            ; RS relative line drawing
  2603.     cmp    al,' '            ; control char?
  2604.     jae    tekrli1            ; ae = no
  2605.     jmp    tektxt            ; process control char
  2606. tekrli1:cmp    al,' '            ; pen up command?
  2607.     jne    tekrli2            ; ne = no, try pen down
  2608.     mov    visible,0        ; do invisible movements
  2609.     jmp    short tekrli3        ; do the command
  2610. tekrli2:cmp    al,'P'            ; pen down command?
  2611.     jne    tekrli4            ; ne = no, return to text mode
  2612.     mov    visible,1        ; set visible moves
  2613.  
  2614. tekrli3:mov    ax,x_coord        ; PC x coordinate of pen
  2615.     mov    bx,y_coord        ;    y coordinate
  2616.     call    pctotek            ; get current pen position in Tek coor
  2617.     xor    cl,cl            ; invisible, moveto
  2618.     call    tekdraw            ; move that point, set oldx and oldy
  2619.     mov    ttstate,offset tekinc    ; next get incremental movement cmds
  2620.     ret
  2621.  
  2622. tekrli4:mov    visible,0        ; bad char, reset visibility
  2623.     mov    ttstate,offset tektxt    ; assume text
  2624. tekrli5:jmp    ttstate            ; deal with bad char
  2625. TEKRLIN    endp
  2626.                     ; interpret RS inc plot command byte
  2627. TEKINC    proc    near            ; get movement character and do cmd
  2628.     cmp    al,' '            ; control char?
  2629.     jae    tekinc1            ; ae = no
  2630.     jmp    tektxt            ; process control char
  2631. tekinc1:mov    bx,oldx
  2632.     mov    cx,oldy
  2633.     test    al,1            ; 'A', 'E', 'I'?  Do by bit fields
  2634.     jz    tekinc2            ; z = no
  2635.     inc    bx            ; adjust beam position
  2636. tekinc2:test    al,2            ; 'B', 'F', 'J'?
  2637.     jz    tekinc4
  2638.     dec    bx
  2639. tekinc4:test    al,4            ; 'D', 'E', 'F'?
  2640.     jz    tekinc8            ; z = no
  2641.     inc    cx
  2642. tekinc8:test    al,8            ; 'H', 'I', 'J'?
  2643.     jz    tekinc9
  2644.     dec    cx
  2645. tekinc9:cmp    bx,0            ; too far left?
  2646.     jge    tekinc10        ; ge = no
  2647.     xor    bx,bx            ; else stop at the left margin
  2648. tekinc10:cmp    bx,maxtekx-1        ; too far left?
  2649.     jle    tekinc11        ; le = no
  2650.     mov    bx,maxtekx-1        ; else stop that the left margin
  2651. tekinc11:cmp    cx,maxteky-1        ; above the top?
  2652.     jle    tekinc12        ; le = not above the top
  2653.     mov    cx,maxteky-1        ; else stop at the top
  2654. tekinc12:cmp    cx,0            ; below bottom?
  2655.     jge    tekinc13        ; ge = not below bottom
  2656.     xor    cx,cx            ; else stop at the bottom
  2657. tekinc13:mov    ax,bx            ; ax is vector x end point
  2658.     mov    oldx,bx
  2659.     mov    bx,cx            ; bx is vector y end point
  2660.     mov    oldy,cx
  2661.     mov    cl,visible
  2662.     jmp    tekdraw            ; move/draw to that point
  2663. tekincb:mov    visible,0
  2664.     jmp    tektxt            ; reparse the bad char
  2665. TEKINC    endp
  2666.     
  2667.  
  2668. crossini proc    near            ; set crosshairs for initial screen
  2669.     mov    ax,xmax            ; right margin minus 7 dots
  2670.     add    ax,7            ; right most dot
  2671.     shr    ax,1            ; central position
  2672.     mov    bx,ybot            ; last scan line
  2673.     shr    bx,1
  2674.     cmp    ax,xcenter        ; same as previous call?
  2675.     jne    crossin2        ; ne = no, recenter
  2676.     cmp    bx,ycenter        ; same as previous call?
  2677.     je    crossin3        ; e = yes, don't recenter crosshairs
  2678. crossin2:mov    xcross,ax        ; save PC coord for crosshair
  2679.     mov    xcenter,ax        ; remember center coord
  2680.     mov    ycross,bx        ; this is the center of the screen
  2681.     mov    ycenter,bx        ; remember center coord
  2682. crossin3:                ; Mouse setup
  2683.     mov    mousebuf,0        ; assume no active mouse driver
  2684.     mov    al,mouse        ; mouse interrupt 33h
  2685.     mov    ah,35h            ; get vector for mouse driver
  2686.     int    dos
  2687.     mov    ax,es
  2688.     cmp    ax,0f000h        ; in ROM Bios?
  2689.     jae    crosin1            ; ae = yes
  2690.     or    ax,bx            ; check for no vector at all
  2691.     jz    crosin1            ; z = none
  2692.     cmp    byte ptr es:[bx],0cfh    ; is this an IRET instruction?
  2693.     je    crosin1            ; e = yes, not our driver
  2694.     mov    ax,msgetbf        ; get state buffer size (bytes) to BX
  2695.     int    mouse
  2696.     add    bx,15            ; round up to next paragraph
  2697.     shr    bx,1
  2698.     shr    bx,1
  2699.     shr    bx,1
  2700.     shr    bx,1            ; bytes to paragraphs
  2701.     mov    ah,alloc        ; allocate memory
  2702.     int    dos
  2703.     jc    crosin1            ; c = failed
  2704.     mov    mousebuf,ax        ; save seg of the mouse status buffer
  2705.     mov    es,ax
  2706.     xor    dx,dx            ; buffer address to es:dx
  2707.     mov    ax,msgetst        ; get mouse state info
  2708.     int    mouse
  2709.     jnc    crosin2            ; nc = presumed success
  2710.     call    mousefree        ; return mouse save buffer
  2711. crosin1:ret
  2712. crosin2:xor    cx,cx            ; minimum horizontal/vertical motion
  2713.     mov    dx,xmax            ; right most char
  2714.     add    dx,7            ; right most dot (counted from 0)
  2715.     mov    ax,mshoriz        ; set min/max horizontal motion
  2716.     int    mouse
  2717.     mov    dx,ybot            ; max y (counted from 0)
  2718.     mov    ax,msvert        ; set min/max vertical motion
  2719.     int    mouse
  2720.     ret
  2721. crossini endp
  2722.  
  2723. ; Routine to trigger the crosshairs, wait for a key to be struck, and send
  2724. ; the typed char (if printable ascii) plus four Tek encoded x,y position
  2725. ; coordinates and then a carriage return.
  2726. ; ax, cx, xcross, ycross operate in PC coordinates.
  2727.      
  2728. CROSHAIR PROC NEAR
  2729.     push    linepat            ; save line drawing pattern
  2730.     mov    linepat,0ffffh        ; reset line type to solid
  2731.     mov    ax,xmax            ; right margin minus 7 dots
  2732.     add    ax,7
  2733.     mov    temp,ax            ; right margin dot
  2734.     call    crosdrawh        ; draw initial crosshairs
  2735.     call    crosdrawv
  2736.     call    setmouse        ; set mouse there too
  2737. crosha1:call    tiseof            ; is stdin at EOF?
  2738.     jc    crosha2            ; c = yes, exit this mode now
  2739.     mov    dl,0ffh
  2740.     mov    ah,dconio        ; read console
  2741.     int    dos
  2742.     jnz    crosha4            ; nz = have char in AL
  2743.     cmp    mousebuf,0        ; is mouse driver active?
  2744.     je    crosha1            ; e = no
  2745.     mov    ax,msread        ; mouse, read status and position
  2746.     int    mouse
  2747.     push    bx            ; save button press information
  2748.     cmp    cx,xcross        ; moved in x direction?
  2749.     je    crosm1            ; e = no
  2750.     push    dx            ; save mouse y
  2751.     call    crosdrawv        ; erase vertical line
  2752.     mov    xcross,cx        ; new position
  2753.     call    crosdrawv        ; draw new vertical line
  2754.     pop    dx
  2755. crosm1:    cmp    dx,ycross        ; moved in y direction?
  2756.     je    crosm2            ; e = no
  2757.     call    crosdrawh        ; erase horizontal line
  2758.     mov    ycross,dx
  2759.     call    crosdrawh        ; draw new horizontal line
  2760. crosm2:    pop    bx
  2761.     test    bx,7            ; mouse, was a button pressed?
  2762.     jz    crosha1            ; z = no
  2763.     mov    al,CR            ; simulate a CR
  2764.  
  2765. crosha4:or    al,al            ; ascii or scan code returned
  2766.     jnz    arrow5            ; nz = ascii char returned
  2767.     call    tiseof            ; is stdin at EOF?
  2768.     jc    crosha2            ; c = yes, exit this mode now
  2769.     mov    ah,coninq        ; read scan code
  2770.     int    dos
  2771.     or    al,al            ; Control-Break?
  2772.     jnz    crosha3            ; nz = no, something else
  2773. crosha2:call    crosdrawh        ; erase crosshairs
  2774.     call    crosdrawv
  2775.     pop    linepat            ; restore line pattern
  2776.     ret                ; exit crosshairs mode
  2777.  
  2778. crosha3:cmp    al,homscn        ; is it 'home'?
  2779.     jne    arrow1            ; ne = no, try other keys
  2780.     call    crosdrawh        ; erase crosshairs
  2781.     call    crosdrawv
  2782.     mov    ax,temp            ; right margin
  2783.     shr    ax,1            ; central position
  2784.     mov    xcross,ax        ; save PC coord for crosshair
  2785.     mov    ax,ybot            ; last scan line
  2786.     shr    ax,1
  2787.     mov    ycross,ax        ; this is the center of the screen
  2788.     call    crosdrawh        ; draw home'd crosshairs
  2789.     call    crosdrawv
  2790.     call    setmouse        ; set mouse there too
  2791.     jmp    crosha1
  2792.  
  2793. arrow1:    cmp    al,lftarr        ; left arrow?
  2794.     jne    arrow2            ; ne = no
  2795.     mov    cx,-1            ; left shift
  2796.     jmp    short xkeys
  2797. arrow2:    cmp    al,rgtarr        ; right arrow?
  2798.     jne    arrow3            ; ne = no
  2799.     mov    cx,1            ; right shift
  2800.     jmp    short xkeys
  2801. arrow3:    cmp    al,uparr        ; up arrow?
  2802.     jne    arrow4            ; ne = no
  2803.     mov    cx,-1            ; up shift
  2804.     jmp    short vertkey
  2805. arrow4:    cmp    al,dnarr        ; down arrow?
  2806.     jne    badkey            ; ne = no, ignore it
  2807.     mov    cx,1                  ; down shift
  2808.     jmp    short vertkey
  2809.  
  2810. badkey:    call    tekbeep            ; tell user we don't understand
  2811.     jmp    crosha1            ; keep going
  2812.  
  2813.                     ; Shifted keys yield ascii keycodes
  2814. arrow5:    cmp    al,'C' and 1fh        ; Control-C?
  2815.     je    crosha2            ; e = yes, exit crosshairs mode now
  2816.     cmp    al,shlftarr        ; shifted left arrow?
  2817.     jne    arrow6            ; ne = no
  2818.     mov    cx,-10            ; big left shift
  2819.     jmp    short xkeys
  2820. arrow6:    cmp    al,shrgtarr        ; shifted right arrow?
  2821.     jne    arrow7            ; ne = no
  2822.     mov    cx,10            ; big right shift
  2823.     jmp    short xkeys
  2824. arrow7:    cmp    al,shuparr        ; shifted up arrow?
  2825.     jne    arrow8            ; ne = no
  2826.     mov    cx,-10            ; big up shift
  2827.     jmp    short vertkey
  2828. arrow8:    cmp    al,shdnarr        ; shifted down arrow?
  2829.     jne    charkey            ; ne = no, send this key as is
  2830.     mov    cx,10            ; big down shift
  2831.     jmp    short vertkey
  2832.  
  2833. xkeys:    call    crosdrawv        ; erase vertical line
  2834.     add    cx,xcross        ; add increment
  2835.     jns    noxc            ; gone too far negative?
  2836.     xor    cx,cx            ; s = yes, make it 0
  2837. noxc:    cmp    cx,temp            ; too far right?
  2838.     jb    xdraw9            ; b = no
  2839.     mov    cx,temp            ; yes, make it the right
  2840. xdraw9: mov    xcross,cx        ; new x value for cross hairs
  2841.     call    crosdrawv        ; draw new vertical line
  2842.     call    setmouse        ; set mouse there too
  2843.     jmp    crosha1
  2844.      
  2845. vertkey:call    crosdrawh        ; erase horizontal line
  2846.     add    cx,ycross        ; adjust cx
  2847.     jns    noyc            ; gone negative?
  2848.     xor    cx,cx            ; s = yes then make 0
  2849. noyc:    cmp    cx,ybot            ; too high?
  2850.     jb    yok            ; b = no
  2851.     mov    cx,ybot            ; make it maximum
  2852. yok:    mov    ycross,cx        ; save new y crosshair
  2853.     call    crosdrawh        ; draw new vertical line
  2854.     call    setmouse        ; set mouse there too
  2855.     jmp    crosha1
  2856.      
  2857. charkey:push    ax            ; preserve char in al
  2858.     call    crosdrawh        ; erase crosshairs
  2859.     call    crosdrawv
  2860.     pop    ax
  2861.     call    outmodem        ; send the break character
  2862.     mov    ax,xcross        ; set beam to xcross,ycross
  2863.     mov    bx,ycross        ; must convert to Tek coordinates
  2864.     call    pctotek            ; scale from PC screen coord to Tek
  2865.     push    ax            ; save around drawing
  2866.     push    bx
  2867.     xor    cx,cx            ; just a move
  2868.     call    tekdraw            ; moveto ax,bx in Tek coord
  2869.     pop    bx            ; recover Tek y
  2870.     pop    ax            ; recover Tek x
  2871.     call    sendpos            ; send position report to host
  2872.     pop    linepat            ; recover current line drawing pattern
  2873.     mov    ttstate,offset tektxt    ; go to TEKTXT next time
  2874.     mov    lastc,0            ; clear last drawing coordinate flag
  2875.     or    status,txtmode        ; set text mode in status byte
  2876.     ret
  2877. CROSHAIR ENDP
  2878.      
  2879. ; draw vertical crosshair line at x = xcross, xor with picture
  2880. crosdrawv proc near
  2881.     mov    al,ccode        ; save current pixel op
  2882.     push    ax
  2883.     push    cx
  2884.     mov    si,xcross        ; move to x= xcross
  2885.     mov    ax,si            ; ending x coord
  2886.     xor    di,di            ; starting y coord
  2887.     mov    bx,ybot            ; bottom y coord
  2888.     mov    cl,pixxor        ; xor pixels
  2889.     call    line            ; draw vertical
  2890.     pop    cx
  2891.     pop    ax            ; recover current pixel op
  2892.     mov    ccode,al        ; restore it
  2893.     ret
  2894. crosdrawv endp
  2895.  
  2896. ; draw horizontal crosshair line at y = ycross, xor with picture
  2897. crosdrawh proc near
  2898.     mov    al,ccode        ; save current pixel op
  2899.     push    ax
  2900.     push    cx
  2901.     mov    di,ycross        ; set y = ycross
  2902.     mov    bx,di            ; ending y
  2903.     xor    si,si            ; starting x
  2904.     mov    ax,temp            ; max x value
  2905.     mov    cl,pixxor        ; set XOR code
  2906.     call    line            ; draw to (xcross+12, ycross)
  2907.     pop    cx
  2908.     pop    ax            ; recover current pixel op
  2909.     mov    ccode,al        ; restore it
  2910.     ret
  2911. crosdrawh endp
  2912.  
  2913. ; Set mouse cursor position to xcross,ycross. Ignored if no active mouse.
  2914. setmouse proc    near
  2915.     cmp    mousebuf,0        ; is mouse driver is active?
  2916.     je    setmou1            ; e = no
  2917.     mov    cx,xcross
  2918.     mov    dx,ycross
  2919.     mov    ax,mswrite        ; set mouse position
  2920.     int    mouse
  2921. setmou1:ret
  2922. setmouse endp
  2923.  
  2924. ; Return DOS memory allocated as mouse status buffer
  2925. mousefree proc    near
  2926.     push    es
  2927.     mov    ax,mousebuf        ; seg of mouse save buffer
  2928.     mov    es,ax            ; allocated segment
  2929.     mov    ah,freemem        ; free it
  2930.     int    dos
  2931.     mov    mousebuf,0        ; clear mouse presence too
  2932.     pop    es
  2933.     ret
  2934. mousefree endp
  2935.  
  2936. ; Return mouse state and free state save buffer
  2937. mousexit proc    near
  2938.     mov    ax,mousebuf        ; segment of state save buffer
  2939.     or    ax,ax            ; is mouse driver active?
  2940.     jz    mousex1            ; z = no
  2941.     push    es
  2942.     mov    es,ax
  2943.     xor    dx,dx            ; address is in es:dx
  2944.     mov    ax,mssetst        ; set mouse driver state from buffer
  2945.     int    mouse
  2946.     pop    es
  2947.     call    mousefree        ; return memory to DOS
  2948. mousex1:ret
  2949. mousexit endp
  2950.  
  2951. ; SENDPOS sends position of cross-hairs to the host.
  2952. ; ax has Tek X and bx has Tek Y coord of center of crosshair     
  2953. SENDPOS PROC NEAR
  2954.     push    bx            ; preserve register
  2955.     call    sendxy            ; send x coord
  2956.     pop    ax
  2957.     call    sendxy            ; send y coord
  2958.     mov    al,cr            ; follow up with cr
  2959.     call    outmodem
  2960.     ret
  2961. SENDPOS ENDP
  2962.  
  2963. ; Write binary number in AX as decimal asciiz to buffer pointer DI.
  2964. dec2di    proc    near        ; output number in ax using base in cx
  2965.                 ; corrupts ax, cx, and dx
  2966.     mov    cx,10
  2967. dec2di1:xor    dx,dx        ; clear high word of numerator
  2968.     div    cx        ; (ax / cx), remainder = dx, quotient = ax
  2969.     push    dx        ; save remainder for outputting later
  2970.     or    ax,ax        ; any quotient left?
  2971.     jz    dec2di2        ; z = no
  2972.     call    dec2di1        ; yes, recurse
  2973. dec2di2:pop    dx        ; get remainder
  2974.     add    dl,'0'        ; make digit printable
  2975.     mov    [di],dl        ; store char in buffer
  2976.     inc    di
  2977.     mov    byte ptr[di],0    ; add terminator
  2978.     ret
  2979. dec2di    endp
  2980.      
  2981. ; SENDXY sends value of ax as Tek encoded bytes
  2982. ; ax is in Tek coordinates     
  2983. SENDXY    PROC    NEAR
  2984.     shl    ax,1
  2985.     shl    ax,1            ; move all but lower 5 bits to ah
  2986.     shl    ax,1
  2987.     shr    al,1
  2988.     shr    al,1            ; move low five bits to low 5 bits
  2989.     shr    al,1
  2990.     or    ah,20h            ; make it a printing char as per TEK
  2991.     xchg    al,ah            ; send high 5 bits first
  2992.     call    outmodem
  2993.     xchg    al,ah            ; then low five bits
  2994.     or    al,20h
  2995.     call    outmodem
  2996.     xchg    ah,al            ; al is first sent byte
  2997.     ret
  2998. SENDXY    ENDP
  2999.      
  3000.      
  3001. SENDID    PROC NEAR            ; pretend VT340
  3002.     mov    bx,offset tekid        ; VT320 identification string
  3003. sndid1: mov    al,[bx]            ; get char from sequence
  3004.     or    al,al            ; end of sequence?
  3005.     jz    sndid0            ; z = yes, return
  3006.     call    outmodem        ; send it out the port
  3007.     inc    bx
  3008.     jmp    sndid1
  3009. sndid0:    ret
  3010. SENDID    ENDP
  3011.      
  3012. ; SENDSTAT - send status and cursor position to host
  3013.      
  3014. SENDSTAT PROC NEAR
  3015.     mov    al,STATUS        ; get tek status
  3016.     or    al,20h            ; make it printable
  3017.     call    OUTMODEM        ; and send it
  3018.     mov    ax,oldx            ; now send x coordinate (oldx is Tek)
  3019.     call    SENDXY
  3020.     mov    ax,oldy            ; and y coordinate (oldy is Tek coord)
  3021.     call    SENDXY
  3022.     mov    al,cr            ; end with a cr
  3023.     call    OUTMODEM
  3024.     ret
  3025. SENDSTAT ENDP
  3026.      
  3027.  
  3028. ; Convert X and Y from PC coordinates to Tek coordinates. AX = X, BX = Y
  3029. ; for both input and output.
  3030. pctotek    proc    near
  3031.     mul    xdiv            ; scale from PC screen coord to Tek
  3032.     div    xmult
  3033.     xchg    bx,ax            ; save Tek x coord in bx
  3034.     neg    ax            ; y axis. Turn upside down for Tek
  3035.     add    ax,ybot
  3036.     mul    ydiv            ; scale y from PC screen coord to Tek
  3037.     div    ymult
  3038.     xchg    ax,bx            ; ax has X, bx has Y in Tek coords
  3039.     ret
  3040. pctotek    endp
  3041.  
  3042. ; Routine to output character in AL to the screen.
  3043.  
  3044. OUTSCRN PROC NEAR            ; put one character to the screen
  3045.     cmp    rxtable+256,0        ; translation turned off?
  3046.     je    outscr2            ; e = yes, no translation
  3047.     push    bx
  3048.     mov    bx,offset rxtable    ; address of translate table
  3049.     xlatb                ; new char is in al
  3050.     and    al,7fh            ; retain only lower seven bits
  3051.     pop    bx
  3052.  
  3053. outscr2:
  3054.     mov    ah,ccode        ; assume transparent chars
  3055.     push    ax            ; save ccode
  3056.     mov    ccode,pixfor        ; write in foreground
  3057.     cmp    chcontrol,0        ; transparent char writing?
  3058.     je    outscr3            ; e = yes
  3059.     or    ccode,pixbak        ; write background dots too
  3060. outscr3:cmp    al,lf            ; this moves down the screen
  3061.     je    outscr4            ; e = yes, a lf
  3062.     cmp    al,' '            ; printable?
  3063.     jb    outscr5            ; b = no
  3064. outscr4:call    testfull        ; check for full screen
  3065. outscr5:call    remcursor        ; remove text cursor symbol
  3066.     call    putc            ; routine to draw characters
  3067.     call    setcursor        ; draw text cursor symbol
  3068.     pop    ax            ; recover ccode
  3069.     mov    ccode,ah
  3070.     ret
  3071. OUTSCRN ENDP
  3072.      
  3073. ; Test if screen is full. If full sound beep, wait for any keyboard input
  3074. ; (skip kbd reading if stdin is redirected).
  3075. testfull proc    near
  3076.     push    ax
  3077.     mov    ax,x_coord
  3078.     cmp    ax,xmax            ; at end of the line?
  3079.     jbe    testfu1            ; be = no
  3080.     mov    x_coord,0        ; wrap to next line
  3081.     add    y_coord,8        ; next row
  3082. testfu1:mov    ax,ybot            ; get last scan line
  3083.     inc    ax            ; number of scan lines
  3084.     cmp    ax,y_coord        ; minus where char bottom needs to go
  3085.     jae    testfu3            ; ae = enough space for char
  3086.     call    tekbeep            ; tell the user we are waiting
  3087.     call    tiseof            ; EOF on redirected stdin?
  3088.     jc    testfu2            ; c = yes, proceed anyway
  3089.     mov    ah,coninq        ; read keyboad via DOS
  3090.     int    dos            ; wait for keystroke
  3091.     or    al,al            ; scan code being returned?
  3092.     jne    testfu2            ; ne = no
  3093.     mov    ah,coninq        ; clear away scan code too
  3094.     int    dos
  3095. testfu2:call    tekcls            ; clear the screen
  3096.     mov    x_coord,0
  3097.     mov    y_coord,0
  3098. testfu3:pop    ax            ; recover current character
  3099.     ret
  3100. testfull endp
  3101.  
  3102. ; Draw text cursor symbol by xor-ing. Sets xcursor,ycursor to symbol position.
  3103. setcursor proc    near
  3104.     cmp    tekcursor,0        ; suppress cursor?
  3105.     je    setcurs0        ; e = yes
  3106.     cmp    cursorst,0        ; is cursor off now?
  3107.     jne    setcurs0        ; ne = no
  3108.     cmp    putc,offset mputc    ; pure mono character display routine?
  3109.     jne    setcurs1        ; ne = no
  3110. setcurs0:ret                ; no cursor for pure mono
  3111. setcurs1:mov    bh,ccode        ; current drawing code, save it
  3112.     mov    bl,chcontrol        ; and transparent writing state
  3113.     push    bx            ; save ccode
  3114.     push    ax
  3115.     mov    ccode,pixxor        ; xor with foreground coloring
  3116.     mov    chcontrol,0        ; transparent characters
  3117.     push    x_coord            ; save current operating point (PC)
  3118.     push    y_coord
  3119.     mov    ax,x_coord        ; where cursor symbol starts, X axis
  3120.     cmp    ax,xmax            ; beyond last character position?
  3121.     jbe    setcurs2        ; be = no
  3122.     mov    ax,xmax            ; yes, stop at last, for wrapping
  3123. setcurs2:mov    xcursor,ax        ; remember where we drew symbol
  3124.     mov    x_coord,ax        ; set this for drawing the symbol
  3125.     mov    ax,y_coord
  3126.     mov    ycursor,ax
  3127.     mov    al,7fh            ; symbol code to draw
  3128.     call    putc            ; routine to draw characters
  3129.     pop    y_coord
  3130.     pop    x_coord
  3131.     pop    ax
  3132.     pop    bx            ; recover ccode
  3133.     mov    ccode,bh
  3134.     mov    chcontrol,bl
  3135.     mov    cursorst,1        ; say cursor is on
  3136.     ret
  3137. setcursor endp
  3138.  
  3139. ; Remove text cursor symbol by xor-ing with itself. Xcursor, ycursor is the
  3140. ; PC coord of the cursor symbol.
  3141. remcursor proc    near
  3142.     cmp    tekcursor,0        ; suppress cursor?
  3143.     je    remcurs0        ; e = yes
  3144.     cmp    cursorst,0        ; is cursor off now?
  3145.     je    remcurs0        ; e = yes
  3146.     cmp    putc,offset mputc    ; pure mono character display routine?
  3147.     jne    remcurs1        ; ne = no
  3148. remcurs0:ret                ; no cursor for pure mono
  3149. remcurs1:mov    bh,ccode        ; current drawing code, save it
  3150.     mov    bl,chcontrol        ; and transparent writing state
  3151.     push    bx            ; save ccode
  3152.     push    ax
  3153.     mov    ccode,pixxor        ; xor with foreground coloring
  3154.     mov    chcontrol,0        ; transparent characters
  3155.     push    x_coord            ; save current operating point (PC)
  3156.     push    y_coord
  3157.     mov    ax,xcursor        ; where last cursor was written
  3158.     mov    x_coord,ax        ; setup for xor writing to remove it
  3159.     mov    ax,ycursor
  3160.     mov    y_coord,ax
  3161.     mov    al,7fh            ; cursor symbol
  3162.     call    putc            ; routine to draw characters
  3163.     pop    y_coord
  3164.     pop    x_coord
  3165.     pop    ax
  3166.     pop    bx            ; recover ccode
  3167.     mov    ccode,bh
  3168.     mov    chcontrol,bl
  3169.     mov    cursorst,0        ; say cursor is off
  3170.     ret
  3171. remcursor endp
  3172.       
  3173. ; TEKCLS routine to clear the screen.
  3174. ; Entry point tekcls1 clears screen without resetting current point.     
  3175. TEKCLS    PROC    NEAR
  3176.     cmp    flags.vtflg,tttek    ; regular Tek terminal?
  3177.     je    tekcls0            ; e = yes
  3178.     test    tekflg,1        ; Tek mode active yet?
  3179.     jnz    tekcls0            ; nz = yes
  3180.     ret                ; else ignore this call
  3181. tekcls0:mov    x_coord,0        ; starting text coordinates
  3182.     mov    y_coord,0
  3183.     mov    oldx,0            ; assumed cursor starting location
  3184.     mov    oldy,maxteky        ;  top right corner (Tek coord)
  3185.     mov    scalex,0        ; clear last plotted point (PC coord)
  3186.     mov    scaley,0
  3187.     mov    lastc,0            ; last parsed x,y coordinate
  3188.     mov    visible,0        ; make lines invisible
  3189.     mov    bypass,0        ; clear bypass condition
  3190.     mov    ttstate,offset tektxt    ; do displayable text
  3191.     mov    prestate,offset tektxt
  3192. tekcls1:push    ax            ; save registers
  3193.     push    cx
  3194.     mov    bl,ccode        ; save pixel op code
  3195.     push    bx
  3196.     cmp    graph_mode,hercules    ; Hercules?
  3197.     jne    tekclsw            ; ne = no
  3198.     call    hgraf            ; set Hercules board to Graphics mode
  3199.     jmp    tekcls7
  3200.  
  3201. tekclsw:cmp    graph_mode,wyse700    ; Wyse 700?
  3202.     jne    tekcls2            ; ne = no
  3203.     call    wygraf            ; set board to Graphics mode & cls
  3204.     jmp    tekcls7
  3205.  
  3206. tekcls2:xor    di,di            ; point to start of screen, di=row
  3207.     mov    ccode,pixbak        ; write in background
  3208.     call    psetup            ; setup graphics routine and es:di
  3209.     mov    cx,4000h        ; CGA, 200 lines times 80 bytes worth
  3210.     cmp    graph_mode,cga        ; cga?
  3211.     je    tekcls3            ; e = yes
  3212.     mov    cx,8000h        ; Olivetti, 400 lines times 80 bytes
  3213.     cmp    graph_mode,olivetti    ; AT&T-Olivetti?
  3214.     je    tekcls3            ; e = yes
  3215.     cmp    graph_mode,toshiba    ; Toshiba?
  3216.     je    tekcls3            ; e = yes
  3217.     cmp    graph_mode,vaxmate    ; VAXmate?
  3218.     jne    tekcls4            ; ne = no
  3219. tekcls3:cld                ; clear screen directly of text stuff
  3220.     xor    ax,ax
  3221.     test    gbcol,7            ; background is dark?
  3222.     jz    tekcls3a        ; z = yes
  3223.     mov    ax,0ffffh        ; light, set all pixels
  3224. tekcls3a:shr    cx,1            ; do words
  3225.     rep    stosw            ; clear the words
  3226.     jmp    short tekcls7
  3227.  
  3228. tekcls4:cmp    graph_mode,ega        ; EGA?
  3229.     je    tekcls5            ; e = yes
  3230.     cmp    graph_mode,monoega    ; EGA with mono display?
  3231.     je    tekcls5            ; e = yes
  3232.     cmp    graph_mode,colorega    ; EGA with medium resolution monitor?
  3233.     je    tekcls5            ; e = yes
  3234.     jmp    short tekcls6        ; else use Bios
  3235.  
  3236. tekcls5:                ; EGA clear screen quickly
  3237.     mov    ax,0ff08h        ; set all 8 bits to be changed
  3238.     call    ega_gc            ; set bit mask register accordingly
  3239.     mov    ax,0003h        ; data rotate reg, write unmodified
  3240.     call    ega_gc            ; 
  3241.     mov    cx,ybot            ; last scan line
  3242.     inc    cx            ; number of scan lines
  3243.     mov    ax,80/2            ; words (2*bytes) per scan line
  3244.     mul    cx
  3245.     mov    cx,ax            ; cx = number of bytes to clear
  3246.     call    fixcolor        ; fix colors first, if req'd
  3247.     mov    al,gbcol        ; select background colour
  3248.     mov    ah,al            ; copy for word stores
  3249.     cld
  3250.     rep    stosw            ; write backgound color
  3251.     jmp    short tekcls7
  3252.  
  3253. tekcls6:push    es            ; clear screen by scrolling up
  3254.     call    tcmblnk            ; clear screen, for Environments
  3255.     pop    es
  3256.  
  3257. tekcls7:xor    si,si            ; starting x  (in case screen is
  3258.     xor    di,di            ; starting y    cleared by user)
  3259.     pop    bx
  3260.     mov    ccode,bl        ; restore pixel op code
  3261.     mov    xcursor,0        ; position of text cursor symbol
  3262.     mov    ycursor,0
  3263.     mov    cursorst,0        ; say text cursor is off (new screen)
  3264.     call    setcursor        ; draw text cursor symbol
  3265.     pop    cx
  3266.     pop    ax
  3267.     ret
  3268. TEKCLS    ENDP
  3269.      
  3270. ; Routine to draw a line on the screen, using TEKTRONIX coordinates.
  3271. ; X coordinate in AX, 0=left edge of screen, 1023=right edge of screen.
  3272. ; Y coordinate in BX, 0=bottom of screen, 779=top of screen.
  3273. ; CL=0 - invisible move, else draw in foreground colors
  3274.      
  3275. TEKDRAW PROC NEAR
  3276.     mov    si,scalex        ; get old x already scaled
  3277.     mov    di,scaley        ; get old y already scaled
  3278.     call    scale             ; scale new end point to PC coords
  3279.     or    cl,cl            ; invisible drawing?
  3280.     jz    moveto            ; z = just move, skip draw part
  3281.     mov    cl,pixfor        ; draw in foreground color
  3282.     call    LINE            ; draw the line
  3283. moveto:    mov    x_coord,ax        ; update text coordinates to match
  3284.     mov    y_coord,bx        ;  last drawn point
  3285.     ret
  3286. TEKDRAW ENDP
  3287.      
  3288. ; Scale TEKTRONIX coordinates to the currently defined screen coordinates
  3289. ; AX holds X axis, BX holds Y axis. Both are changed from Tektronix coord
  3290. ; to PC coordinates by this procedure.
  3291. SCALE    PROC    NEAR
  3292.     push    dx
  3293.     push    si
  3294.     cmp    ax,1023            ; limit x axis
  3295.     jbe    scale1            ; be = not out of bounds
  3296.     mov    ax,1023
  3297. scale1:    cmp    bx,779            ; limit y axix
  3298.     jbe    scale2            ; be = not out of bounds
  3299.     mov    bx,779
  3300. scale2:    mov    oldx,ax            ; save current Tek x for next draw
  3301.     mov    oldy,bx            ; save current Tek y for next draw
  3302.     mul    xmult            ; scale x-coord
  3303.     mov    si,xdiv            ; get the divisor
  3304.     shr    si,1            ; halve it
  3305.     add    ax,si            ; add in - to round to nearest integer
  3306.     adc    dx,0
  3307.     div    xdiv
  3308.     push    ax
  3309.     mov    ax,bx
  3310.     mul    ymult            ; scale y-coord
  3311.     mov    si,ydiv            ; get divisor
  3312.     shr    si,1            ; halve it
  3313.     add    ax,si            ; add in - to round to nearest integer
  3314.     adc    dx,0
  3315.     div    ydiv
  3316.     mov    bx,ybot
  3317.     sub    bx,ax            ; put new Y in right reg
  3318.     jns    scale3            ; ns = not too far
  3319.     xor    bx,bx
  3320. scale3:    pop    ax            ; put new X in right reg
  3321.     mov    scalex,ax        ; save scaled values
  3322.     mov    scaley,bx
  3323.     pop    si
  3324.     pop    dx
  3325.     ret
  3326. SCALE    ENDP
  3327.       
  3328. ; LINE    Subroutine to plot a line with endpoints in AX,BX and SI,DI.
  3329. ;    fast line drawing routine for the IBM PC
  3330. ;
  3331. ; Registers at CALL
  3332. ; -----------------
  3333. ; SI=Start X coord, all in PC coordinates
  3334. ; DI=Start Y coord
  3335. ; AX=End X coord
  3336. ; BX=End Y coord
  3337. ; CCODE=pixel operation code
  3338. ; BP= line drawing pattern (is changed here by rotation)
  3339. ; registers are all unchanged
  3340.      
  3341. LINE    PROC    NEAR
  3342.     push    ax
  3343.     push    bx
  3344.     push    cx
  3345.     push    dx
  3346.     push    si
  3347.     push    di
  3348.     push    es
  3349.     mov    bp,linepat        ; store active line pattern word in BP
  3350.     mov    dl,ccode        ; existing pixel op code
  3351.     push    dx            ; save around line drawing
  3352.     mov    ccode,cl    ; save color code in ccode for use by plot()
  3353.             ; first get coord to achieve increasing x; deltax >= 0
  3354.     sub    ax,si            ; deltax = x2 - x1
  3355.     jge    line1            ; ge = going to the right, as desired
  3356.     neg    ax            ; make deltax non-negative
  3357.     sub    si,ax            ; swap the x coordinates
  3358.     xchg    bx,di            ; swap the y coordinates too
  3359.                 ; second, compute deltay. ax = deltax, si = x1
  3360. line1:    sub    bx,di            ; deltay = y2 - y1
  3361.     call    psetup            ; setup display adapter for plotting
  3362.                     ;  and setup es:di to screen memory
  3363.   ; Choose algorithm based on |deltay| < |deltax| (use shallow) else steep.
  3364.   ; We arrange matters such that both deltas are non-negative.
  3365.     cmp    bx,0            ; deltay
  3366.     jge    line2            ; ge = non-negative
  3367.     neg    linelen
  3368.     neg    bx            ; make non-negative
  3369. line2:    cmp    bx,ax            ; |deltay| versus |deltax|
  3370.     jbe    shallow            ; be = do shallow algorithm
  3371.     jmp    steep            ; else do steep algorithm
  3372.  
  3373.     ; shallow algorithm, move along x, di=y1, bx=deltay, si=x1, ax=deltax
  3374. shallow:add    bx,bx            ; bx = 2*deltay
  3375.     mov    cx,ax            ; cx = number of steps (deltax here)
  3376.     inc    cx            ; loop dec's cx before testing
  3377.     mov    dx,bx            ; dx holds error
  3378.     sub    dx,ax            ; error = 2*deltay - deltax
  3379.     add    ax,ax            ; ax = 2*|deltax|
  3380. shal1:    call    plotptr            ; Plot(x,y)
  3381.     cmp    dx,0
  3382.     jle    shal2            ; le =     error <= 0
  3383.     call    pincy            ; increment y by one scan line
  3384.     sub    dx,ax            ; error = error - 2*deltax
  3385. shal2:    add    dx,bx            ; error = error + 2*deltay
  3386.     inc    si            ; x = next dot right
  3387.     loop    shal1
  3388.     jmp    short plotex
  3389.  
  3390.     ; steep algorithm, move along y, di=y1, bx=deltay, si=x1, ax=deltax
  3391. steep:    add    ax,ax            ; ax = 2*deltax
  3392.     mov    dx,ax            ; dx holds error
  3393.     sub    dx,bx            ; error = 2*deltax(bx) - deltay (bx)
  3394.     mov    cx,bx            ; cx = number of steps (deltay here)
  3395.     inc    cx            ; loop dec's cx before testing
  3396.     add    bx,bx            ; bx = 2*|deltay|
  3397. stee1:    call    plotptr            ; Plot(x,y) x = ax, y = di
  3398.     cmp    dx,0
  3399.     jle    stee2            ; le  error <= 0
  3400.     inc    si            ; x = next dot right
  3401.     sub    dx,bx            ; error = error - 2*deltay
  3402. stee2:    add    dx,ax            ; error = error + 2*deltax
  3403.     call    pincy            ; increment y
  3404.     loop    stee1
  3405. ;;;    jmp    plotex
  3406.  
  3407. plotex:    pop    dx            ; al has orginal pixel op
  3408.     mov    ccode,dl        ; restore it
  3409.     pop    es
  3410.     pop    di
  3411.     pop    si
  3412.     pop    dx            ; restore the world
  3413.     pop    cx
  3414.     pop    bx
  3415.     pop    ax
  3416.     ret
  3417. LINE    ENDP
  3418.  
  3419. ; Draw a rectangle.
  3420. ;  lower left corner: x = param[0], y = param[2], Tek coordinates
  3421. ;  distance: dx = param[4], dy = param[6], Tek coordinates, all positive
  3422. rectdraw proc    near
  3423.     push    x_coord
  3424.     push    y_coord
  3425.     mov    ax,param[0]        ; lower left corner is start, x part
  3426.     mov    bx,param[2]        ; y part
  3427.     push    ax            ; x0
  3428.     push    bx            ; y0
  3429.     xor    cl,cl            ; moveto
  3430.     call    tekdraw
  3431.     pop    bx
  3432.     pop    ax
  3433.     add    bx,param[6]        ; y0 + dy
  3434.     mov    cl,1            ; draw x0,y0  to  x0,y0+dy
  3435.     push    ax
  3436.     push    bx
  3437.     call    tekdraw
  3438.     pop    bx
  3439.     pop    ax
  3440.     add    ax,param[4]        ; x0+dx
  3441.     mov    cl,1            ; draw x0,y0+dy  to  x0+dx,y0+dy
  3442.     push    ax
  3443.     call    tekdraw
  3444.     pop    ax
  3445.     mov    bx,param[2]        ; y0
  3446.     push    bx
  3447.     mov    cl,1
  3448.     call    tekdraw
  3449.     pop    bx
  3450.     mov    ax,param[0]        ; x0
  3451.     mov    cl,1
  3452.     call    tekdraw            ; complete the box
  3453.     pop    y_coord
  3454.     pop    x_coord
  3455.     ret
  3456. rectdraw endp
  3457.  
  3458. ; Fill a rectangle with a given pattern.
  3459. ;  lower left corner: x = param[0], y = param[2], Tek coordinates
  3460. ;  distance: dx = param[4], dy = param[6], Tek coordinates, all positive
  3461. ;  fill pattern = param[8]
  3462. rectfil    proc    near
  3463.     push    oldx
  3464.     push    oldy            ; save regular point/line old coords
  3465.     mov    ax,param        ; get Tek X coord of lower left corner
  3466.     mov    bx,param[2]        ; get Tek Y coord
  3467.     call    scale            ; convert to PC in ax,bx, scalex/y
  3468.     mov    rectx1,ax        ; lower left corner in PC coords
  3469.     mov    recty1,bx
  3470.     mov    ax,param        ; convert ending points, start Tek X
  3471.     add    ax,param[4]        ; Tek X + DX
  3472.     mov    bx,param[2]        ; start Tek Y
  3473.     add    bx,param[6]        ; Tek Y + DY
  3474.     call    scale
  3475.     pop    oldy
  3476.     pop    oldx
  3477.     mov    rectx2,ax        ; upper right corner PC X coord
  3478.     mov    recty2,bx        ; upper right corner PC Y coord
  3479.     mov    si,rectx1        ; starting x PC coord to si
  3480.     mov    di,recty2        ; starting y PC coord to di
  3481.     mov    cx,recty1        ; plotting from top down on screen
  3482.     sub    cx,bx            ; cx = # scan lines - 1
  3483.     mov    numlines,cx        ; remember here
  3484.     mov    bx,param[8]        ; fill pattern number
  3485.     or    bx,bx            ; zero?
  3486.     jz    rectfi1            ; z = yes, use current pointer
  3487.     cmp    bx,numfil        ; pattern number is too large?
  3488.     ja    rectfi1            ; a = yes, use current pointer
  3489.     dec    bx            ; count internally from 0
  3490.     shl    bx,1            ; make this a word pointer
  3491.     mov    bx,fillist[bx]        ; get pointer to pattern
  3492.     mov    fillptr,bx        ; remember it here
  3493. rectfi1:mov    cx,rectx2        ; ending x coord
  3494.     sub    cx,rectx1        ; number of horizontal pixels - 1
  3495.     inc    cx            ; number of horizontal pixels
  3496.     call    psetup            ; set up dsp and di to screen offset
  3497.             ; di points to whole byte, do bits in byte in gfplot
  3498. rectfi2:push    bx
  3499.      mov    bx,recty1        ; lower screen y (larger value)
  3500.     sub    bx,numlines        ; alignment: global screen sync
  3501.     and    bx,7            ; modulo 8
  3502.     add    bx,fillptr        ; offset of fill pattern start
  3503.     mov    bl,[bx]            ; pattern byte
  3504.     mov    fill,bl            ; save here for gfplot
  3505.     pop    bx
  3506.     call    gfplot            ; line fill routine
  3507.     call    pincy            ; next line
  3508.     dec    numlines
  3509.     jns    rectfi2            ; ns = more to do
  3510.     ret
  3511. rectfil    endp
  3512.  
  3513. ;;;;;;; EGA plot support routines
  3514. psetupe    proc    near            ; EGA setup for plotting
  3515.     push    ax
  3516.     mov    linelen,80        ; for y going down screen by pincy
  3517.     mov    ax,segscn        ; set es to screen memory segment
  3518.     mov    es,ax
  3519.     mov    ax,0205h        ; mode: write mode 2
  3520.     call    ega_gc
  3521.     mov    ax,0003h        ; assume writing bits directly
  3522.     test    ccode,pixfor+pixbak    ; direct foreground/background write?
  3523.     jnz    psete2            ; nz = yes
  3524.     mov    ax,1003h        ; assume OR
  3525.     test    ccode,pixor        ; OR?
  3526.     jnz    psete2            ; nz = yes
  3527.     mov    ax,1803h        ; assume XOR
  3528.     test    ccode,pixxor        ; inverting bits?
  3529.     jnz    psete2            ; nz = yes
  3530.     mov    ax,0803h        ; then use AND
  3531. psete2:    call    ega_gc            ; set controller
  3532.     mov    ax,80            ; compute starting point in regen buff
  3533.     mul    di
  3534.     mov    di,ax            ; di = di * 80
  3535.     pop    ax
  3536.     ret
  3537. psetupe    endp
  3538.  
  3539. pincye    proc    near            ; EGA inc y
  3540.     add    di,linelen        ; includes sign of deltay
  3541.     ret
  3542. pincye    endp
  3543.  
  3544. pltega    proc    near        ; EGA plot(x,y). x is in si, y is in di
  3545.     ror    bp,1            ; rotate line pattern
  3546.     jc    pltega1            ; c = a 1 bit to be plotted
  3547.     cmp    ccode,pixfor+pixbak    ; plot both 1's and 0's?
  3548.     je    pltega1            ; e = yes
  3549.     ret                ; else ignore the 0 bit
  3550. pltega1:push    bx
  3551.     push    si
  3552.     push    di
  3553.     mov    bx,si            ; want si/8 for bytes along line
  3554.     shr    si,1
  3555.     shr    si,1
  3556.     shr    si,1
  3557.     add    di,si            ; starting point in regen buffer
  3558.     and    bx,0007h        ; leave lower 3 bits for bit in byte
  3559.     mov    bh,masktab[bx]        ; 0-7 into bit mask in byte, x pos
  3560.     mov    bl,ccode        ; get line type code
  3561.     call    ega_plt
  3562.     pop    di
  3563.     pop    si
  3564.     pop    bx
  3565.     ret
  3566. pltega    endp
  3567.  
  3568. ; Plot bit pattern in "fill" as 8 horizontal pixels, starting at x,y (si,di)
  3569. ; and continuing across the line for cx pixels. psetupe has been called.
  3570. bpltega    proc    near        ; EGA plot(x,y). x is in si, y is in di
  3571.     push    bx
  3572.     push    cx
  3573.     push    si
  3574.     push    di
  3575.     mov    bx,si            ; want si/8 for bytes along line
  3576.     shr    si,1
  3577.     shr    si,1
  3578.     shr    si,1
  3579.     add    di,si            ; starting byte in regen buffer
  3580.                     ; di = offset in regen buffer
  3581.     and    bl,7            ; get bit in byte (di = byte aligned)
  3582.     jz    bplteg1            ; z = aligned already
  3583.     xchg    bl,cl            ; get shift to cl, low count to bl
  3584.     mov    bh,fill            ; 8-bit fill pattern
  3585.     mov    al,bh            ; get complement of pattern too
  3586.     not    al
  3587.     shl    bh,cl            ; trim cl bits from the left
  3588.     shr    bh,cl
  3589.     shl    al,cl            ; trim them from the right edge
  3590.     shr    al,cl            ; restore pattern
  3591.     xchg    cl,bl            ; put count back in cx
  3592.     add    cl,bl            ; add bits taken care of
  3593.     adc    ch,0
  3594.     jmp    short bplteg2        ; do this partial byte now
  3595.  
  3596. bplteg1:mov    bh,fill            ; fill pattern
  3597.     mov    al,bh            ; make inverted pattern
  3598.     not    al
  3599.     cmp    cx,8            ; do all 8 bits?
  3600.     jae    bplteg2            ; ae = yes
  3601.     push    cx            ; final byte fixup
  3602.     sub    cl,8            ; cl = - (number of bits to omit)
  3603.     neg    cl            ; cl = number of bits to omit
  3604.     mov    al,bh            ; get complement of pattern too
  3605.     not    al
  3606.     shr    bh,cl            ; trim them from the right edge
  3607.     shl    bh,cl            ; restore pattern
  3608.     shr    al,cl            ; trim them from the right edge
  3609.     shl    al,cl            ; restore pattern
  3610.     pop    cx
  3611. bplteg2:push    ax
  3612.     cmp    ccode,pixfor+pixbak    ; do both fore and background?
  3613.     jne    bplteg2a        ; ne = no
  3614.     push    bx
  3615.     mov    bh,al            ; get complemented pattern
  3616.     mov    bl,pixbak        ; write background
  3617.     call    ega_plt
  3618.     pop    bx
  3619. bplteg2a:mov    bl,ccode        ; get line type code
  3620.     call    ega_plt
  3621. bplteg3:pop    ax
  3622.     inc    di            ; next byte right
  3623.     sub    cx,8            ; did these
  3624.     cmp    cx,0            ; anything left to do?
  3625.     jg    bplteg1            ; a = yes, repeat
  3626.     pop    di
  3627.     pop    si
  3628.     pop    cx
  3629.     pop    bx
  3630.     ret
  3631. bpltega    endp
  3632.  
  3633. ;;;;;;;; CGA plot support routines
  3634. ; The CGA graphics memory mapping in mode 6 (640 by 200) is 8 dots per byte,
  3635. ; left most dot in the high bit, 80 bytes per scan line, scan line segments
  3636. ; alternating between 0b800h (even lines 0, 2, ...) and 0ba00h (odd lines).
  3637. psetupc    proc    near            ; CGA setup for plotting
  3638.     push    ax
  3639.     push    cx
  3640.     mov    linelen,80        ; 80 bytes per scan line
  3641.     mov    cx,segscn
  3642.     mov    es,cx
  3643.     mov    cx,di            ; save copy of di, start y line
  3644.                     ; compute starting point in regen buff
  3645.     shr    di,1            ; half the lines in each bank
  3646.     mov    ax,80            ; 80 bytes per line
  3647.     mul    di
  3648.     mov    di,ax            ; di = di * 80 / 2
  3649.     test    cx,1            ; even or odd line
  3650.     jz    psetc1            ; z = even
  3651.     add    di,2000h        ; offset to odd bank (seg 0ba00h)
  3652. psetc1:    and    di,3fffh
  3653.     pop    cx
  3654.     pop    ax
  3655.     ret
  3656. psetupc    endp
  3657.  
  3658. pincyc    proc    near            ; CGA inc y
  3659.     cmp    linelen,0        ; increasing or decreasing y?
  3660.     jl    pinyc2            ; l = decreasing
  3661.     cmp    di,2000h        ; in upper bank now?
  3662.     jb    pinyc1            ; b = no, in lower bank
  3663.     add    di,linelen        ; add a line
  3664. pinyc1:    add    di,2000h        ; switch banks
  3665.     and    di,3fffh        ; roll over address
  3666.     ret
  3667. pinyc2:    cmp    di,2000h        ; in upper bank now?
  3668.     jae    pinyc4            ; ae = yes
  3669.     add    di,linelen        ; subtract a line
  3670. pinyc4:    add    di,2000h        ; switch banks
  3671.     and    di,3fffh        ; roll over address
  3672.     ret
  3673. pincyc    endp
  3674.  
  3675. pltcga    proc    near        ; CGA plot(x,y). x is in si, y is in di
  3676.     push    bx        ; used for HGA and Wyse plots also.
  3677.     push    si
  3678.     push    di
  3679.     ror    bp,1            ; rotate line pattern
  3680.     jc    pltcg6            ; c = 1 bit to be plotted
  3681.     cmp    ccode,pixfor+pixbak    ; plot both 1's and 0's?
  3682.     jne    pltcg3            ; ne = no
  3683.  
  3684. pltcg6:    mov    bx,si            ; want si/8 for bytes along line
  3685.     shr    si,1
  3686.     shr    si,1
  3687.     shr    si,1
  3688.     add    di,si            ; starting point in regen buffer
  3689.     and    bx,0007h        ; leave lower 3 bits for bit in byte
  3690.                     ; di = offset in regen buffer
  3691.     mov    bh,masktab[bx]        ; 0-7 into bit mask in byte. x position
  3692.     mov    bl,ccode        ; get line type code
  3693.     test    bl,pixfor+pixor        ; draw in foreground color or OR?
  3694.     jz    pltcg1            ; z = no
  3695.     test    bl,pixor        ; OR?
  3696.     jnz    pltcg5            ; nz = yes
  3697.     test    gfcol,7            ; is foreground dark?
  3698.     jz    pltcg4            ; z = yes, punch a hole
  3699. pltcg5:    or    es:[di],bh        ; drawn
  3700.     jmp    short pltcg3
  3701. pltcg1:    test    bl,pixbak        ; draw in background (erase)?
  3702.     jz    pltcg2            ; z = no
  3703.     test    gbcol,7            ; is background light?
  3704.     jnz    pltcg5            ; nz = yes
  3705. pltcg4:    not    bh            ; invert the bit
  3706.     and    es:[di],bh        ; erase the dot
  3707.     jmp    short pltcg3
  3708. pltcg2:    xor    es:[di],bh        ; xor in this color
  3709. pltcg3:    pop    di
  3710.     pop    si
  3711.     pop    bx
  3712.     ret
  3713. pltcga    endp
  3714.  
  3715. ; Plot bit pattern in fill as 8 horizontal pixels, starting at x,y (si,di)
  3716. ; and continuing across the line for cx pixels. psetupc has been called.
  3717. bpltcga    proc    near        ; CGA plot(x,y). x is in si, y is in di
  3718.     push    bx        ; used for HGA and Wyse plots also.
  3719.     push    cx
  3720.     push    si
  3721.     push    di
  3722.     mov    bx,si            ; want si/8 for bytes along line
  3723.     shr    si,1
  3724.     shr    si,1
  3725.     shr    si,1
  3726.     add    di,si            ; starting byte in regen buffer
  3727.                     ; di = offset in regen buffer
  3728.     and    bl,7            ; get bit in byte (di = byte aligned)
  3729.     jz    bpltcg5            ; z = aligned already
  3730.     xchg    bl,cl            ; get shift to cl, low count to bl
  3731.     mov    bh,fill            ; 8-bit fill pattern
  3732.     shl    bh,cl            ; trim cl bits from the left
  3733.     shr    bh,cl
  3734.     push    cx
  3735.     mov    al,0ffh            ; 1's are original bits to be saved
  3736.     sub    cl,8            ; max field width is 8 bits
  3737.     neg    cl            ; 8-number of bits trimmed from left
  3738.     shl    al,cl            ; al now holds save-field bit pattern
  3739.     pop    cx
  3740.     xchg    cl,bl            ; put count back in cx
  3741.     add    cl,bl            ; add bits taken care of
  3742.     adc    ch,0
  3743.     jmp    short bpltcg4        ; do this partial byte now
  3744.  
  3745. bpltcg5:mov    bh,fill            ; fill pattern
  3746.     xor    al,al            ; assume saving no bits
  3747.     cmp    cx,8            ; do all 8 bits?
  3748.     jae    bpltcg4            ; ae = yes
  3749.     push    cx            ; final byte fixup
  3750.     mov    al,0ffh            ; 1's are original bits to be saved
  3751.     shl    al,cl
  3752.     shr    al,cl            ; al now holds save-field bit pattern
  3753.     sub    cl,8            ; cl = - (number of bits to omit)
  3754.     neg    cl            ; cl = number of bits to omit
  3755.     shr    bh,cl            ; trim them from the right edge
  3756.     shl    bh,cl            ; restore pattern
  3757.     pop    cx
  3758. bpltcg4:mov    bl,ccode        ; get line type code
  3759.     cmp    bl,pixfor+pixbak    ; set both fore and background?
  3760.     jne    bpltcg9            ; ne = no
  3761.     test    gfcol,7            ; is foreground dark?
  3762.     jnz    bpltcg8            ; nz = no
  3763.     not    bh            ; invert the bit pattern
  3764.     or    bh,al            ; set bits to be saved
  3765.     sub    bh,al            ; trim off saved bits from this field
  3766. bpltcg8:mov    ah,es:[di]        ; get contents of memory cell
  3767.     and    ah,al            ; preserve bit field given by al
  3768.     or    bh,ah            ; mask in saved bits
  3769.     mov    es:[di],bh        ; write the byte
  3770.     jmp    short bpltcg3        ; done
  3771. bpltcg9:test    bl,pixfor+pixor        ; draw in foreground?
  3772.     jz    bpltcg1            ; z = no
  3773.     test    bl,pixor        ; OR?
  3774.     jnz    bpltcg7            ; nz = yes
  3775.     test    gfcol,7            ; is foreground dark?
  3776.     jz    bpltcg6            ; z = yes, punch a hole
  3777. bpltcg7:or    es:[di],bh        ; drawn
  3778.     jmp    short bpltcg3
  3779. bpltcg1:test    bl,pixbak        ; draw as background (erase)?
  3780.     jz    bpltcg2            ; z= do not draw as background (erase)
  3781.     test    gbcol,7            ; is background light?
  3782.     jz    bpltcg6            ; z = no
  3783.     or    es:[di],bh        ; drawn
  3784.     jmp    short bpltcg3
  3785. bpltcg6:not    bh
  3786.     and    es:[di],bh        ; erase the dots
  3787.     jmp    short bpltcg3
  3788. bpltcg2:xor    es:[di],bh        ; xor in this color
  3789. bpltcg3:inc    di            ; next byte right
  3790.     sub    cx,8            ; did these
  3791.     cmp    cx,0            ; anything left to do?
  3792.     jg    bpltcg5            ; a = yes, repeat
  3793.     pop    di
  3794.     pop    si
  3795.     pop    cx
  3796.     pop    bx
  3797.     ret
  3798. bpltcga    endp
  3799.  
  3800. ;;;;;;; Wyse-700 plot support routines
  3801. ; The Wyse graphics memory map in mode 0D3h (1280 by 800) is 8 dots per byte,
  3802. ; left most dot in the high bit, 160 bytes per scan line, scan line segments
  3803. ; sequence as 0a000h even lines, and same for odd lines
  3804. psetupw proc    near            ; Wyse setup for plotting
  3805.     push    ax
  3806.     push    cx
  3807.     push    dx
  3808.     mov    linelen,160        ; for y going down screen by incy
  3809.     mov    ax,segscn        ; base segment of display memory
  3810.     mov    es,ax
  3811.     mov    cx,di            ; save copy of di, start y line
  3812.                     ; compute starting point in regen buff
  3813.     shr    di,1            ; half the lines in each bank
  3814.     mov    ax,160
  3815.     mul    di
  3816.     mov    di,ax            ; di = di * 160 / 2
  3817.     mov    dx,wymode
  3818.     shr    cx,1            ; compute bank from 1 lsb of line num
  3819.     jnc    psetw2            ; nc = it is in bank 0 (0b000h)
  3820.     mov    ax,wybodd        ; select odd bank
  3821.     out    dx,al
  3822.     jmp    short psetw3
  3823. psetw2: mov    ax,wybeven        ; select even bank
  3824.     out    dx,al
  3825. psetw3: mov    bnkchan, al        ; bank has changed
  3826.     pop    dx
  3827.     pop    cx
  3828.     pop    ax
  3829.     ret
  3830. psetupw endp
  3831.  
  3832. ;
  3833. ; Wyse-700 has two banks. Line 0, 2, 4 ... are in bank 0, and 1, 3, 5 ... are
  3834. ; in bank 1. Lines 0 and 1 have same addresses, lines 2 and 3 have same
  3835. ; addresses etc. We have to change bank every time Y changes but we
  3836. ; have to count new address only after two Y-value changes. Variable
  3837. ; bnkchan is a flag for us to know into which bank to write.
  3838. ;
  3839. pincyw    proc    near            ; Wyse inc y, step offset of line
  3840.     push    ax
  3841.     push    dx
  3842.     mov    dx,wymode        ; Wyse conrol register
  3843.     mov    al,wybeven        ;
  3844.     cmp    bnkchan,wybeven        ; was last write into even bank ?
  3845.     jne    pincywe            ; ne = no
  3846.     mov    al,wybodd        ; yes, set ready for odd bank
  3847.     out    dx,al            ;
  3848.     mov    bnkchan,al        ; set to odd
  3849.     jmp    short pincywo
  3850. pincywe:mov    al,wybeven        ; set ready foe even bank
  3851.     out    dx,al            ; select it
  3852.     mov    bnkchan,al        ; set to odd
  3853. pincywo:cmp    linelen,0        ; increasing y?
  3854.     jg    pinyw2            ; g = yes
  3855.     cmp    al,wybeven        ; from high (1) to low (0) bank ?
  3856.     je    pinyw4            ; e = yes
  3857.     add    di,linelen        ; no, add a line
  3858.     jmp    short pinyw4
  3859. pinyw2: cmp    al,wybodd        ; from low (0) to high (1) bank ?
  3860.     je    pinyw4            ; e = yes
  3861.     add    di,linelen        ; no, add a line
  3862. pinyw4: and    di,0ffffh        ; roll over address
  3863.     pop    dx
  3864.     pop    ax
  3865.     ret
  3866. pincyw    endp
  3867.  
  3868. ;;;;;;; HGA plot support routines
  3869. ; The HGA graphics memory mapping in mode 255 (720 by 348) is 8 dots per byte,
  3870. ; left most dot in the high bit, 90 bytes per scan line, scan line segments
  3871. ; sequence as 0b000h, 0b200h, 0b400h, 0b800h for lines 0-3 and repeat 90 bytes
  3872. ; higher for the rest.
  3873. psetuph    proc    near            ; HGA setup for plotting
  3874.     push    ax
  3875.     push    cx
  3876.     mov    linelen,90        ; for y going down screen by incy
  3877.     mov    ax,segscn        ; base segment of display memory
  3878.     mov    es,ax
  3879.     mov    cx,di            ; save copy of di, start y line
  3880.                     ; compute starting point in regen buff
  3881.     shr    di,1            ; quarter the lines in each bank
  3882.     shr    di,1
  3883.     mov    ax,90
  3884.     mul    di
  3885.     mov    di,ax            ; di = di * 90 / 4
  3886.     and    cx,3            ; compute bank from 2 lsb of line num
  3887.     jcxz    pseth2            ; z means it is in bank 0 (0b000h)
  3888. pseth1:    add    di,2000h        ; add offset for each bank
  3889.     loop    pseth1            ; do cx times
  3890. pseth2:    pop    cx
  3891.     pop    ax
  3892.     ret
  3893. psetuph    endp
  3894.  
  3895. pincyh    proc    near            ; HGA inc y, step offset of line
  3896.     cmp    linelen,0        ; increasing y?
  3897.     jg    pinyh2            ; g = yes
  3898.     cmp    di,2000h        ; in lowest for four banks?
  3899.     ja    pinyh1            ; a = no
  3900.     add    di,linelen        ; yes, add a line
  3901. pinyh1:    add    di,6000h        ; move back by adding a lot
  3902.     and    di,7fffh        ; roll over address
  3903.     ret
  3904. pinyh2:    cmp    di,6000h        ; in top most bank?
  3905.     jb    pinyh4            ; b = no
  3906.     add    di,linelen        ; yes, first add a line
  3907. pinyh4:    add    di,2000h        ; switch to next bank
  3908.     and    di,7fffh        ; roll over address
  3909.     ret
  3910. pincyh    endp
  3911.  
  3912. ;;;;;;; AT&T-Olivetti, Toshiba, VAXmate Graphics Adapter plot support routines
  3913. ; The graphics memory mapping in 640 by 400 mode is 8 dots per byte,
  3914. ; left most dot in the high bit, 80 bytes per scan line, scan line segments
  3915. ; sequence as 0b800h, 0ba00h, 0bc00h, 0be00h for lines 0-3 and repeat 80 bytes
  3916. ; higher for the rest. Use Hercules line incrementing (inc y) and CGA dot
  3917. ; writing. This is a monographic display.
  3918. psetupo    proc    near            ; setup for plotting
  3919.     push    ax
  3920.     push    cx
  3921.     mov    linelen,80        ; for y going down screen by incy
  3922.     mov    ax,segscn        ; base segment of display memory
  3923.     mov    es,ax
  3924.     mov    cx,di            ; save copy of di, start y line
  3925.                     ; compute starting point in regen buff
  3926.     shr    di,1            ; quarter the lines in each bank
  3927.     shr    di,1
  3928.     mov    ax,80
  3929.     mul    di
  3930.     mov    di,ax            ; di = di * 80 / 4
  3931.     and    cx,3            ; compute bank from 2 lsb of line num
  3932.     jcxz    pseto2            ; z means it is in bank 0 (0b800h)
  3933. pseto1:    add    di,2000h        ; add offset for each bank
  3934.     loop    pseto1            ; do cx times
  3935. pseto2:    pop    cx
  3936.     pop    ax
  3937.     ret
  3938. psetupo    endp
  3939.  
  3940. ;;;;;;;; Monochrome, simulate dots with text char
  3941. psetupm    proc    near
  3942.     mov    linelen,1        ; 80 characters but one line
  3943.     ret
  3944. psetupm    endp
  3945.  
  3946. pltmon    proc    near            ; Monochrome dot plot
  3947.     mov    x_coord,si        ; put dot at row=di, col=si, PC Coord
  3948.     mov    y_coord,di
  3949.     push    ax
  3950.     mov    al,'+'            ; our dot character
  3951.     call    mputc            ; display text char
  3952.     pop    ax
  3953.     ret
  3954. pltmon    endp
  3955.  
  3956. ; Plot bit pattern in fill as 8 horizontal pixels, starting at x,y (si,di)
  3957. ; and continuing across the line for cx pixels. Destroys CX.
  3958. bpltmon    proc    near        ; Mono plot(x,y). x is in si, y is in di
  3959.     jmp    pltmon        ; a dummy for the present
  3960. bpltmon    endp
  3961.  
  3962. pincym    proc    near            ; Monochrome inc y
  3963.     add    di,linelen        ; includes sign
  3964.     ret
  3965. pincym    endp
  3966.  
  3967. ; GPUTC - a routine to send text characters from font to true graphics boards
  3968. ; such as EGA, Hercules or CGA. Char is in al. Drawing routine ptr is gcplot.
  3969.      
  3970. gputc    proc    near
  3971.     cmp    al,' '            ; control character or space?
  3972.     ja    gputc2            ; a = no, display the char
  3973.     je    gputc1            ; e = space char
  3974.     jmp    putctrl            ; else handle controls at putctrl
  3975. gputc1:    cmp    spcontrol,0        ; non-destructive space?
  3976.     jne    gputc2            ; ne = no, do actual writing
  3977.     cmp    chcontrol,0        ; write transparently?
  3978.     jne    gputc2            ; ne = no, opaque, draw the char
  3979.     call    testfull        ; check on full screen
  3980.     jmp    incx            ; move to next char position
  3981.  
  3982. gputc2:    push    bx            ; first save some registers
  3983.     push    cx
  3984.     push    es
  3985.     push    di
  3986.      mov    bl,al            ; now BL has char to be displayed
  3987.     and    bl,7fh            ; no high bits allowed here
  3988.                     ; set board mode
  3989.     mov    di,y_coord        ; get current y coord (char bottom)
  3990.     sub    di,7            ; start 7 lines higher
  3991.     jnc    gputc3            ; nc = ok
  3992.     xor    di,di            ; move up to first line
  3993.     mov    y_coord,7        ; and reset scan line indicator
  3994. gputc3:    call    psetup    ; enter with di=line number, sets es:di to start of
  3995.             ; line in regen buffer and sets byte-wide plot mode
  3996.     mov    si,x_coord        ; si has x-axis in PC screen coord
  3997.     xor    bh,bh
  3998.     sub    bx,32            ; characters in font start at 32
  3999.     shl    bx,1
  4000.     shl    bx,1            ; 8 bytes per char, hence * 8
  4001.     shl    bx,1
  4002.     mov    cx,8            ; 8 bytes (scan lines) to transfer
  4003.     call    gcplot            ; call character plot routine
  4004.     call    incx            ; move to next char position
  4005.     pop    di
  4006.     pop    es
  4007.     pop    cx
  4008.     pop    bx
  4009.     ret
  4010. gputc    endp
  4011.  
  4012. putctrl    proc    near            ; CONTROL CHARS = cursor movement
  4013.     cmp    al,FF            ; formfeed?
  4014.      jne    putct0            ; ne = no
  4015.     jmp    TEKCLS            ; FF clears the screen
  4016.  
  4017. putct0:    cmp    al,BS            ; BS? sends (logical) cursor back one
  4018.     jne    putct2            ; ne = no, try next
  4019.     sub    x_coord,8        ; delete 8 dots (move left)
  4020.     jnc    putct1            ; nc = ok
  4021.     mov    x_coord,0        ; limit to left margin
  4022. putct1:    cmp    bscontrol,0        ; non-destructive backspace?
  4023.     je    putctx            ; e = yes
  4024.     push    x_coord            ; destructive backspace
  4025.     mov    al,spcontrol        ; save this
  4026.     push    ax
  4027.     mov    spcontrol,1        ; destructive space
  4028.     mov    al,' '            ; a space to be written
  4029.     call    gputc            ; write it
  4030.     pop    ax
  4031.     mov    spcontrol,al        ; restore space control
  4032.     pop    x_coord            ; restore cursor
  4033.     ret
  4034.  
  4035. putct2:    cmp    al,TAB            ; tabs move forward one char position
  4036.     jne    putct4            ; ne = not a tab
  4037. ;;;    OR    X_COORD,7*8
  4038.     jmp    incx            ; let incx move cursor right one col
  4039.  
  4040. putct4:    cmp    al,CR            ; <CR> means go to beginning of line
  4041.     jne    putct5
  4042.     mov    x_coord,0        ; zero the x coordinate
  4043.     ret
  4044.  
  4045. putct5:    cmp    al,LF            ; <LF> means go down 8 pixels (1 line)
  4046.     jne    putct7            ; ne = not LF
  4047.     add    y_coord,8        ; border managed by outscrn and incx
  4048.     ret
  4049.  
  4050. putct7:    cmp    al,VT            ; <VT> move up screen 1 line (8 pixels)
  4051.     jne    putctx
  4052.     sub    y_coord,8        ; subtract one line (8 pixels)
  4053.     jnc    putctx            ; nc = space left
  4054.     mov    y_coord,8        ; else set to top of screen
  4055. putctx:    ret
  4056. putctrl    endp
  4057.  
  4058. mputc    proc    near            ; MONO put char in AL via Bios
  4059.     push    bx            ; updates x_coord,y_coord with
  4060.     push    cx            ; new cursor position
  4061.     push    dx
  4062.     xor    ah,ah            ; marker for cursor setting not needed
  4063.     cmp    al,' '            ; control code?
  4064.     jae    mputc1            ; ae = no, printable
  4065.     call    putctrl            ; do cursor arithmetic
  4066.     mov    ah,1            ; marker to set cursor but no display
  4067.  
  4068. mputc1:    push    ax            ; save char and marker
  4069.     mov    cl,3            ; char cell is 8 x 8 dots
  4070.     mov    ax,x_coord        ; get resulting cursor PC positions
  4071.     shr    ax,cl
  4072.     mov    dl,al            ; column
  4073.     mov    ax,y_coord
  4074.     sub    ax,7            ; minus 7 dots, like other modes
  4075.     jnc    mputc2            ; nc = non-negative
  4076.     mov    ax,7            ; else start at the top
  4077.     mov    y_coord,ax        ; here too
  4078. mputc2:    shr    ax,cl
  4079.     mov    dh,al            ; row
  4080.     mov    ah,2            ; set cursor to x_coord,y_coord
  4081.     xor    bh,bh            ; page 0
  4082.     int    screen
  4083.     pop    ax
  4084.     or    ah,ah            ; write a char in al?
  4085.     jnz    mputcx            ; nz = no
  4086.     mov    ah,09h            ; write char at cursor postion
  4087.     mov    cx,1            ; just one char
  4088.     xor    bh,bh            ; page 0
  4089.     mov    bl,gfcol        ; foreground coloring
  4090.     int    screen
  4091.     inc    dl            ; next column
  4092.     mov    ah,2            ; set real cursor ahead of last char
  4093.     int    screen
  4094.     call    incx            ; move logical cursor
  4095. mputcx:    pop    dx
  4096.     pop    cx
  4097.     pop    bx
  4098.     ret
  4099. mputc    endp
  4100.  
  4101. incx    proc    near            ; move the logical cursor right
  4102.     mov    ax,xmax
  4103.     add    ax,8            ; last column+1
  4104.     cmp    ax,x_coord        ; beyond right most column?
  4105.     jae    incx1            ; ae = no
  4106.     mov    x_coord,ax        ; set up for wrap
  4107.     ret
  4108. incx1:    add    x_coord,8        ; shift the (logical) cursor right
  4109.     ret                ;  one character cell
  4110. incx    endp
  4111.  
  4112. ; Character plot routine. Enter with bx pointing at font array for char
  4113. ; cx = number of bytes in char font, es:di = screen memory. Worker for gputc.
  4114. ; ccode: pixbak=plot in backgrd colors, pixfor=foregrd, pixxor=xor with screen
  4115. gcplot    proc    near
  4116.     mov    al,ccode        ; save original ccode and fill pattern
  4117.     mov    ah,fill
  4118.     push    ax
  4119.     or    bx,bx            ; dealing with "space"?
  4120.     jnz    gcplot1            ; nz = no
  4121.     cmp    spcontrol,0        ; transparent space?
  4122.     jne    gcplot2            ; ne = no, do destructive space
  4123. gcplot1:cmp    chcontrol,0        ; transparent char writing?
  4124.     je    gcplot3            ; e = yes
  4125. gcplot2:mov    ccode,pixfor+pixbak    ; write both fore and back ground
  4126. gcplot3:mov    al,font[bx]        ; EGA byte plot: get bits from font
  4127.     push    bx
  4128.     push    cx
  4129.     mov    cx,si            ; x-axis in PC screen coordinates
  4130.     and    cx,7            ; bit in byte across the screen
  4131.     ror    al,cl            ; rotate pattern for gfplot filling
  4132.     mov    cx,8            ; do 8 bits on the line
  4133.     mov    fill,al            ; use "fill" as fill pattern
  4134.     call    gfplot            ; fill a scan line for cx bits
  4135.     call    pincy            ; next scan line (linelen is preset)
  4136.     pop    cx
  4137.     pop    bx
  4138.     inc    bx            ; next byte of char pattern
  4139.     loop    gcplot1
  4140.     pop    ax
  4141.     mov    ccode,al        ; recover variables
  4142.     mov    fill,ah
  4143.     ret
  4144. gcplot    endp
  4145.  
  4146. ; routines to manipulate ega graphics controller and mode register
  4147. ; command code in al, value in ah - destroys al and dx
  4148.      
  4149. ega_gc    proc    near            ; ega graphics controller
  4150.     mov    dx,3ceh
  4151.     out    dx,al            ; output command code
  4152.     inc    dx            ; dx is now data port
  4153.     mov    al,ah            ; get value to al
  4154.     out    dx,al            ; output value
  4155.     ret
  4156. ega_gc    endp
  4157. ega_md    proc    near            ; ega mode controller
  4158.     mov    dx,3c4h
  4159.     out    dx,al            ; output command code
  4160.     inc    dx            ; dx is now data port
  4161.     mov    al,ah            ; get value to al
  4162.     out    dx,al            ; output value
  4163.     ret
  4164. ega_md endp
  4165.      
  4166. ; Plot eight pixels using an EGA board
  4167. ; Enter with ES:[DI] pointing to screen address of byte,
  4168. ; bh has pattern of bits to be set, bl has attributes:
  4169. ;  pixbak = draw in background color, pixfor = draw in foreground color,
  4170. ;  pixor = OR with foreground color, pixxor = XOR with foreground color.
  4171. ; registers preserved
  4172. ; Note: this function operates on 8 pixels. One bits in bh select pixels to
  4173. ; be changed, bl determines which color planes will be affected for every
  4174. ; selected pixel.
  4175. ega_plt proc    near
  4176.     push    ax
  4177.     push    dx
  4178.     mov    dx,3ceh            ; (ega_gc) unprotect the bit positions
  4179.     mov    al,8            ; command to set bit mask register
  4180.     out    dx,al            ; output command code
  4181.     inc    dx            ; dx is now data port
  4182.     mov    al,bh            ; get pixels to be modified (1's)
  4183.     out    dx,al            ; output value (end of ega_gc)
  4184.     pop    dx
  4185.  
  4186.     mov    ah,gfcol        ; foreground color bit planes
  4187. ega1:    test    bl,pixfor+pixor        ; write foreground or OR?
  4188.     jnz    ega3            ; nz = yes
  4189.     mov    ah,gbcol        ; background color bit planes
  4190.     test    bl,pixbak        ; write in background coloring?
  4191.     jnz    ega3            ; nz = yes
  4192.     mov    ah,0fh            ; xor, touch each bit plane
  4193. ega3:    mov    al,es:[di]        ; latch byte
  4194.     mov    es:[di],ah        ; merge with untouched bits
  4195.     pop    ax
  4196.     ret
  4197. ega_plt endp
  4198.  
  4199. ; Presence test for Wyse-700: info in B000h and B800h are supposed to be equal
  4200. chkwyse    proc    near
  4201.     push    es
  4202.     push    ds
  4203.     mov    ax,0b800h        ; CGA segment
  4204.     mov    es,ax
  4205.     mov    ax,0b000h        ; Mono segment
  4206.     mov    ds,ax
  4207.     mov    ch,byte ptr es:[0]    ; CGA seg
  4208.     mov    cl,byte ptr ds:[0]    ; Mono seg
  4209.     push    cx            ; save original contents
  4210.     mov    byte ptr ds:[0],ch    ; copy CGA to Mono
  4211.     cmp    byte ptr ds:[0],ch    ; if different then not Wyse
  4212.     jne    chkwys1            ; ne = not Wyse
  4213.     not    byte ptr es:[0]        ; change CGA contents
  4214.     not    ch            ; and original pattern
  4215.     cmp    ch,byte ptr ds:[0]    ; if different then not Wyse
  4216.     jne    chkwys1            ; ne = not Wyse
  4217.     pop    cx
  4218.     mov    byte ptr es:[0],ch    ; restore CGA
  4219.     mov    byte ptr ds:[0],cl    ; restore Mono
  4220.     pop    ds
  4221.     pop    es
  4222.     clc
  4223.     ret
  4224.  
  4225. chkwys1:pop    cx
  4226.     mov    byte ptr es:[0],ch    ; restore CGA
  4227.     mov    byte ptr ds:[0],cl    ; restore Mono
  4228.     pop    ds
  4229.     pop    es
  4230.     stc
  4231.     ret
  4232. chkwyse    endp
  4233. ;
  4234. ; routine to set Wyse-700 board to graphics mode - 1280 * 800 & cls
  4235. ;
  4236. WYGRAF    PROC    NEAR
  4237.     push    ax
  4238.     push    bx            ; save used registers
  4239.     push    cx
  4240.     push    dx
  4241.     push    di
  4242.     xor    al,al
  4243.     mov    dx,wystoff        ; map video memory offset to zero
  4244.     out    dx,al            ;
  4245.     mov    dx,wystseg        ; map video memory segment to zero
  4246.     out    dx,al            ;
  4247.     mov    ax,segwyse        ; set es to Wyse start segment
  4248.     mov    es,ax            ;
  4249.     mov    al,wybeven        ; graph mode - even bank
  4250.     mov    dx,wymode        ; Wyse mode control register
  4251.     out    dx,al            ; select even bank
  4252.     cld
  4253.     xor    ax,ax            ; zero ax
  4254.     xor    di,di            ; start from zero
  4255.     mov    cx,0ffffh        ; clear 10000h bytes, whole even bank
  4256.     rep    stosb            ; store blanking char in whole screen
  4257.     mov    al,wybodd        ; graph mode - odd bank
  4258.     mov    dx,wymode        ; select it
  4259.     out    dx,al            ;
  4260.     xor    ax,ax            ; zero ax
  4261.     xor    di,di            ;
  4262.     mov    cx,0ffffh        ; clear 10000h bytes, whole odd bank
  4263.     rep    stosb            ; store blanking char in whole screen
  4264.     mov    bnkchan, 0        ; assume bank 0
  4265.     pop    di            ; restore regs
  4266.     pop    dx
  4267.     pop    cx
  4268.     pop    bx
  4269.     pop    ax
  4270.     ret
  4271. WYGRAF    ENDP
  4272.  
  4273. ; routine to set Hercules card to graphics mode - both pages are enabled
  4274.      
  4275. HGRAF    PROC    NEAR
  4276.     push    ax
  4277.     push    bx            ; save used registers
  4278.     push    cx
  4279.     push    si
  4280.     mov    al,grph            ; graph mode
  4281.     lea    si,gtable        ;  requires graphics table
  4282.     xor    bx,bx
  4283.     mov    cx,4000h        ; clear 4000h words
  4284.     test    gbcol,7            ; any (light) background color bits?
  4285.     jz    hgraf1            ; z = no, we are ok
  4286.     dec    bx            ; light background, set all the bits
  4287. hgraf1:    call    setmd            ; and set the mode
  4288.     pop    si
  4289.     pop    cx
  4290.     pop    bx
  4291.     pop    ax
  4292.     ret
  4293. HGRAF    ENDP
  4294.      
  4295. ; set Hercules card to text mode
  4296.      
  4297. HTEXT    PROC    NEAR
  4298.     push    ax
  4299.     push    bx
  4300.     push    cx
  4301.     push    si
  4302.     mov    al,text            ; text mode
  4303.     lea    si,ttable        ; requires text table
  4304.     mov    bx,0720h        ; blank value (space, white on black)
  4305.     mov    cx,2000            ; whole screen to clear (80*25)
  4306.     call    setmd            ; set the mode
  4307.     pop    si
  4308.     pop    cx
  4309.     pop    bx
  4310.     pop    ax
  4311.     ret
  4312. HTEXT    ENDP
  4313.      
  4314. ; Hercules mode set - called from HTEXT and HGRAF
  4315.      
  4316. SETMD    PROC    NEAR
  4317.     push    dx
  4318.     push    ax
  4319.     mov    dx,config        ; configuration port
  4320.     mov    al,genable        ; allow graphics mode to be set
  4321.     out    dx,al
  4322.     pop    ax
  4323.     push    ax
  4324.     push    cx            ; save count
  4325.     mov    dx,cntrl        ; control port
  4326.     out    dx,al            ; set to text or graphics
  4327.     mov    dx,index        ; send 12 bytes from table to 6845
  4328.     mov    cx,12            ; number of registers to load
  4329.     xor    ah,ah            ; start with register 0 of 6845
  4330.     cld
  4331. setmd1:    jmp    $+2            ; small pause for hardware
  4332.     mov    al,ah            ; ah is counter
  4333.     out    dx,al            ; set register
  4334.     inc    dx            ; point to data port
  4335.     lodsb                ; get next byte in table
  4336.     jmp    $+2            ; small pause for hardware
  4337.     out    dx,al            ; and send to 6845
  4338.     inc    ah            ; next register
  4339.     dec    dx            ; point to register port
  4340.     loop    setmd1            ; and continue 'til cx=0
  4341.     pop    cx            ; recover count
  4342.     cld
  4343.     push    di
  4344.     push    es
  4345.     mov    ax,segscn        ; start of screen
  4346.     mov    es,ax
  4347.     xor    di,di
  4348.     mov    ax,bx            ; get blanking character
  4349.     rep    stosw            ; store blanking char in whole screen
  4350.     pop    es
  4351.     pop    di
  4352.     mov    dx,cntrl        ; now to re-enable screen
  4353.     pop    ax            ; get mode
  4354.     or    al,scrn_on        ; enable screen
  4355.     out    dx,al
  4356.     pop    dx
  4357.     ret
  4358. SETMD    ENDP
  4359.      
  4360. teksave    proc    near        ; saves graphics screen from page 0 to page 1
  4361.     push    si
  4362.     push    di
  4363.     cmp    gpage,0        ; only graphics page 0 on display board?
  4364.     je    teksavx        ; e = yes, no saving possible here
  4365.     mov    si,segscn    ; segment (!) of current screen
  4366.     cmp    graph_mode,ega
  4367.     je    teksav1
  4368.     cmp    graph_mode,monoega
  4369.     je    teksav1
  4370.     cmp    graph_mode,colorega
  4371.     je    teksav1
  4372.     cmp    graph_mode,hercules
  4373.     je    teksav2
  4374.     jmp    short teksavx    ; else nothing
  4375. teksav1:mov    di,segega+800h    ; EGA page 1 screen segment
  4376.     call    egasr        ; call common save/restore code
  4377.     jmp    short teksavx
  4378. teksav2:mov    di,seghga+800h    ; Hercules page 1 screen segment
  4379.     call    hgasr        ; call common save/restore code
  4380. teksavx:pop    di
  4381.     pop    si
  4382.     ret
  4383. teksave    endp
  4384.  
  4385. tekrest    proc    near        ; restores graphics screen in page 1 to page 0
  4386.     push    si
  4387.     push    di
  4388.     cmp    gpage,0        ; only graphics page 0 on display board?
  4389.      jne    tekres0        ; ne = no, more so work to do here
  4390.     call    tekcls1        ;  else clear the screen to color it
  4391.     jmp    short tekresx    ;  and exit
  4392. tekres0:mov    di,segscn    ; segment (!) of new graphics screen
  4393.     cmp    graph_mode,ega
  4394.     je    tekres1
  4395.     cmp    graph_mode,monoega
  4396.     je    tekres1
  4397.     cmp    graph_mode,colorega
  4398.     je    tekres1
  4399.     cmp    graph_mode,hercules
  4400.     je    tekres2
  4401.     jmp    short tekresx    ; else nothing
  4402. tekres1:mov    si,segega+800h    ; segment of EGA page 1
  4403.     call    egasr        ; call common save/restore code
  4404.     jmp    short tekresx
  4405. tekres2:mov    si,seghga+800h    ; segment of Hercules page 1
  4406.     call    hgasr        ; call common save/restore code
  4407. tekresx:pop    di
  4408.     pop    si
  4409.     ret
  4410. tekrest    endp
  4411.  
  4412. egasr    proc    near        ; common code for Tek ega save/restore ops
  4413.     push    ax
  4414.     push    cx
  4415.     push    dx
  4416.     mov    ax,0f00h    ; enable 4 plane set/resets
  4417.     call    ega_gc        ; set controller
  4418.     mov    ax,0f01h    ; enable Set/Reset register
  4419.     call    ega_gc
  4420.     mov    ax,0f02h    ; set color compare register for 4 planes
  4421.     call    ega_gc
  4422.     mov    ax,0905h    ; set mode reg: write latches, read mode
  4423.     call    ega_gc
  4424.     mov    ax,0ff02h    ; enable all planes
  4425.     call    ega_md
  4426.     mov    cx,ybot        ; last scan line
  4427.     inc    cx        ; number of scan lines
  4428.     mov    ax,80        ; bytes per scan line
  4429.     mul    cx
  4430.     mov    cx,ax
  4431.     push    es        ; save es
  4432.     push    ds        ; save ds
  4433.     mov    es,di        ; destination, set es to video memory
  4434.     mov    ds,si        ; source, set ds to video memory
  4435.     xor    si,si        ; clear offset fields
  4436.     xor    di,di
  4437.     cld            ; byte moves for ega adaptor
  4438.     rep    movsb        ; copy from page (ds:si) to page (es:di)
  4439.     pop    ds        ; recover ds
  4440.     pop    es        ; and other registers
  4441.     xor    ax,ax        ; disable 4 plane set/resets
  4442.     call    ega_gc        ; set controller
  4443.     mov    ax,0001h    ; disable Set/Reset register
  4444.     call    ega_gc        ; set controller
  4445.     mov    ax,0002h    ; disable color compare register
  4446.     call    ega_gc
  4447.     mov    ax,1005h    ; set mode reg: write latches, odd/even
  4448.     call    ega_gc
  4449.     pop    dx
  4450.     pop    cx
  4451.     pop    ax
  4452.     ret
  4453. egasr    endp
  4454.  
  4455. hgasr    proc    near        ; Hercules save restore screen
  4456.     push    cx
  4457.     mov    cx,4000h    ; number of words to move
  4458.     push    es        ; save es
  4459.     push    ds        ; save ds
  4460.     mov    es,di        ; destination, set es to video memory
  4461.     mov    ds,si        ; source, set ds to video memory
  4462.     xor    si,si        ; clear offset fields
  4463.     xor    di,di
  4464.     cld
  4465.     rep    movsw        ; copy from page [si] to page [di]
  4466.     pop    ds        ; recover ds
  4467.     pop    es        ; and other registers
  4468.     pop    cx
  4469.     ret
  4470. hgasr    endp
  4471.  
  4472. dump    proc    FAR            ; Write screen as TIFF v5.0 file
  4473.     push    ax
  4474.     push    bx
  4475.     push    cx
  4476.     push    dx
  4477.     push    si
  4478.     push    di
  4479.     call    remcursor        ; remove the cursor from the screen
  4480.     mov    si,offset dumpname    ; name of dump file
  4481.     mov    di,offset tempname    ; destination
  4482.     push    es
  4483.     push    ds
  4484.     pop    es
  4485.     mov    cx,dumplen        ; length of dump name
  4486.     cld
  4487.     repnz    movsb            ; copy it, asciiz
  4488.     pop    es
  4489.     mov    ax,offset tempname    ; address to ax for unique
  4490.     call    tunique            ; get unique name into ax
  4491.     mov    dx,ax            ; ds:dx is asciiz filename
  4492.     xor    cx,cx            ; normal attributes
  4493.     mov    ah,creat2        ; create the file
  4494.     int    dos
  4495.     jc    dmp2            ; c = failure
  4496. dmp1:    mov    dhandle,ax        ; file handle
  4497.     call    dmpdate            ; do time stamp
  4498.     cmp    plotptr,offset pltcga    ; using CGA style graphics?
  4499.     jne    dmp2            ; ne = no
  4500.     call    cgadmp            ; do CGA style dump routine
  4501.     jmp    short dmp3
  4502. dmp2:    call    egadmp
  4503. dmp3:    mov    cursorst,1        ; pretend cursor was on
  4504.     call    remcursor        ; restore the cursor to the screen
  4505.     mov    cursorst,1        ; say it is on
  4506.     pop    di
  4507.     pop    si
  4508.     pop    dx
  4509.     pop    cx
  4510.     pop    bx
  4511.     pop    ax
  4512.     ret
  4513. dump    endp
  4514.  
  4515. ; CGA TIFF 5.0 screen-to-file dump routine
  4516. cgadmp    proc    near
  4517.     push    es            ; do the bookkeeping math first
  4518.     mov    bps.entval,1        ; bits/sample, mono
  4519.     mov    photo.entval,1        ; mono, one bit after the other
  4520.     mov    word ptr cmap.entcnt,0    ; no palette color map entries
  4521.     mov    ax,xmax            ; image width - 8 pixels
  4522.     add    ax,8            ; plus 8, for pixels per line
  4523.     mov    iwidth.entval,ax    ; store in directory
  4524.     mov    xresval,ax        ; x resolution
  4525.     mov    xresval+2,0        ; high order part
  4526.     mov    ax,ybot            ; lines per screen - 1
  4527.     inc    ax            ; lines per screen
  4528.     mov    ilength.entval,ax    ; image length, scan lines
  4529.     mov    yresval,ax        ; y resolution
  4530.     mov    yresval+2,0        ; high order part
  4531.     mov    cx,25            ; try dividing into this many strips
  4532. cgadmp5:xor    dx,dx            ; image pixels
  4533.     mov    ax,yresval        ; number of scan lines
  4534.     div    cx            ; try dividing into 25 strips,ax=quo
  4535.     or    dx,dx            ; did we get null remainder?
  4536.     loopnz    cgadmp5            ; nz = no, try again with fewer strips
  4537.     inc    cx            ; inc for dec by loop, cx = # strips
  4538.     mov    word ptr strip.entcnt,cx ; store number of strips
  4539.     mov    word ptr sbc.entcnt,cx    ; store number of strip byte counts
  4540.     mov    rps.entval,ax        ; rows per strip
  4541.     push    cx
  4542.     mov    cx,iwidth.entval    ; dots per line (row)
  4543.     shr    cx,1            ; get bytes/row
  4544.     shr    cx,1
  4545.     shr    cx,1
  4546.     mul    cx            ; rows/strip * bytes/row = bytes/strip
  4547.     pop    cx
  4548.     push    cx            ; save strip count for loop below
  4549.     push    ds            ; ax = bytes per strip
  4550.     pop    es            ; es:di to our data segment
  4551.     mov    di,offset stripbc    ; where to write strip byte counts
  4552.     cld
  4553.     rep    stosw            ; write ax as bytes/strip, cx times
  4554.     pop    cx            
  4555.     mov    dx,ax            ; bytes/strip = increment, put here
  4556.     mov    di,offset stripoff    ; where we write
  4557.     mov    ax,offset pixdata-offset header ; where first strip starts
  4558. cgadmp4:stosw                ; write strip file offset
  4559.     mov    word ptr [di],0        ; high order part
  4560.     add    di,2            ; next double word
  4561.     add    ax,dx            ; next file strip offset
  4562.     loop    cgadmp4            ; do all strip offsets
  4563.                     ; file i/o starts here
  4564.     mov    bx,dhandle        ; dump's file handle
  4565.     mov    dx,offset header    ; write TIFF header and directory
  4566.     mov    cx,tifflen        ; length of header plus directory
  4567.     mov    ah,write2
  4568.     int    dos
  4569.     jc    cgadmp2            ; c = failure
  4570.     xor    di,di            ; start at y = top
  4571.     call    psetup            ; setup cga and di
  4572.     mov    cx,ybot            ; number of scan lines-1
  4573.     inc    cx            ; number of scan lines
  4574. cgadmp1:push    cx
  4575.     mov    cx,iwidth.entval    ; dots per line (row)
  4576.     shr    cx,1            ; get bytes/row
  4577.     shr    cx,1
  4578.     shr    cx,1            ; line length, bytes
  4579.     mov    dx,di            ; offset in screen buffer
  4580.     mov    bx,dhandle        ; file handle
  4581.     push    ds
  4582.     mov    ax,segscn        ; screen seg
  4583.     mov    ds,ax
  4584.     mov    ah,write2        ; write directly from screen memory
  4585.     int    dos
  4586.     pop    ds
  4587.     jc    cgadmp2            ; c = failure
  4588.     call    pincy            ; next line down, y = y + 1
  4589.     pop    cx
  4590.     loop    cgadmp1            ; do all scan lines
  4591. cgadmp2:mov    ah,close2        ; close the file
  4592.     int    dos
  4593.     mov    dhandle,-1        ; set handle to unused
  4594.     pop    es
  4595.     ret
  4596. cgadmp    endp
  4597.  
  4598. ; EGA TIFF 5.0 screen-to-file dump routine
  4599. egadmp    proc    near
  4600.     push    es            ; do the bookkeeping math first
  4601.     mov    bps.entval,4        ; bits/sample, iRGB
  4602.     mov    photo.entval,3        ; photo interp, palette
  4603.     mov    word ptr cmap.entcnt,3*16 ; palette color map entries
  4604.     mov    ax,xmax            ; image width - 8 pixels
  4605.     add    ax,8            ; plus 8, for pixels per line
  4606.     mov    iwidth.entval,ax    ; store in directory
  4607.     mov    xresval,ax        ; x resolution
  4608.     mov    xresval+2,0        ; high order part
  4609.     mov    ax,ybot            ; lines per screen - 1
  4610.     inc    ax            ; lines per screen
  4611.     mov    ilength.entval,ax    ; image length, scan lines
  4612.     mov    yresval,ax        ; y resolution
  4613.     mov    yresval+2,0        ; high order part
  4614.     mov    cx,25            ; try dividing into this many strips
  4615. egadmp10:xor    dx,dx            ; image pixels
  4616.     mov    ax,yresval        ; number of scan lines
  4617.     div    cx            ; try dividing into 25 strips, ax=quo
  4618.     or    dx,dx            ; did we get null remainder?
  4619.     loopnz    egadmp10        ; nz = no, try again with fewer strips
  4620.     inc    cx            ; inc for dec by loop, cx = # strips
  4621.     mov    word ptr strip.entcnt,cx ; store number of strips
  4622.     mov    word ptr sbc.entcnt,cx    ; store number of strip byte counts
  4623.     mov    rps.entval,ax        ; rows per strip
  4624.     shl    ax,1
  4625.     shl    ax,1            ; times 4 bits / pixel
  4626.     push    cx
  4627.     mov    cx,iwidth.entval    ; dots per line (row)
  4628.     shr    cx,1            ; get bytes/row
  4629.     shr    cx,1
  4630.     shr    cx,1
  4631.     mul    cx            ; rows/strip * bytes/row = bytes/strip
  4632.     pop    cx
  4633.     push    cx            ; save strip count for loop below
  4634.     push    ds            ; ax = bytes per strip
  4635.     pop    es            ; es:di to our data segment
  4636.     mov    di,offset stripbc    ; where to write strip byte counts
  4637.     cld
  4638.     rep    stosw            ; write ax as bytes/strip, cx times
  4639.     pop    cx            
  4640.     mov    dx,ax            ; bytes/strip = increment, put here
  4641.     mov    di,offset stripoff    ; where we write
  4642.     mov    ax,offset pixdata-offset header ; where first strip starts
  4643.     xor    bx,bx
  4644. egadmp11:stosw                ; write strip file offset
  4645.     mov    es:[di],bx        ; high order part
  4646.     add    di,2            ; next double word
  4647.     add    ax,dx            ; next file strip offset
  4648.     adc    bx,0
  4649.     loop    egadmp11        ; do all strip offsets
  4650.                     ; screen to file i/o starts here
  4651.     mov    bx,dhandle        ; dump's file handle
  4652.     mov    dx,offset header    ; write TIFF header and directory
  4653.     mov    cx,tifflen        ; length of header plus directory
  4654.     mov    ah,write2
  4655.     int    dos
  4656.     jnc    egadmp12
  4657.     jmp    egadmp9            ; c = failure
  4658. egadmp12:
  4659.     xor    di,di            ; start at y = top
  4660.     call    psetup            ; setup adapter and es:di
  4661.     xor    di,di
  4662.     mov    bx,offset tempname    ; set buffer address
  4663.     mov    cx,ybot            ; number of scan lines-1
  4664.     inc    cx            ; number of scan lines
  4665. egadmp1:push    cx            ; save scan line counter
  4666.     mov    cx,iwidth.entval    ; dots per line (row)
  4667.     shr    cx,1            ; get bytes/row
  4668.     shr    cx,1
  4669.     shr    cx,1            ; 8*dots across the screen (640)
  4670. egadmp2:push    cx            ; save counter of inner loops
  4671.     mov    cx,4            ; number of planes to do
  4672.     mov    word ptr [bx],0        ; clear the four bytes for this loop
  4673.     mov    word ptr [bx+2],0
  4674. egadmp3:push    cx            ; save plane counter
  4675.     push    bx            ; don't advance buffer pointer here
  4676.     mov    dx,3ceh            ; (ega_gc)
  4677.     mov    al,4            ; command to select read map register
  4678.     out    dx,al            ; output command code
  4679.     inc    dx            ; dx is now data port
  4680.     mov    al,cl            ; do planes 3(I), then 2(R),1(G),0(B)
  4681.     dec    al            ; cx is one higher than plane
  4682.     out    dx,al            ; output value (end of ega_gc)
  4683.     mov    al,es:[di]        ; latch byte
  4684.                     ; got 8 bits from a plane
  4685.     mov    cx,4            ; do this for four output bytes
  4686. egadmp4:mov    ah,[bx]            ; eventually iRGB in each nibble
  4687.     shl    al,1            ; get left most pixel bit in plane
  4688.     jnc    egadmp5
  4689.     or    ah,8            ; set high nibble least sig bit
  4690. egadmp5:shl    al,1            ; odd numbered pixel
  4691.      rcl    ah,1            ; set low nibble least sig bit if c
  4692.     mov    [bx],ah
  4693.     inc    bx            ; next byte
  4694.     loop    egadmp4            ; do all four bytes
  4695.  
  4696.     pop    bx
  4697.     pop    cx            ; restore plane counter
  4698.     loop    egadmp3            ; do all planes
  4699.  
  4700.     inc    di            ; next screen memory address
  4701.     add    bx,4            ; just did four bytes
  4702.     cmp    bx,offset tempname+80    ; at end of 80 bytes?
  4703.     jb    egadmp6            ; b = no
  4704.     call    egadmpw            ; write the buffer
  4705.     mov    bx,offset tempname    ; reset buffer address
  4706.     jnc    egadmp6            ; nc = success
  4707.     pop    cx            ; clean stack
  4708.     pop    cx
  4709.     jmp    egadmp9            ; error
  4710.  
  4711. egadmp6:pop    cx            ; recover bytes per line counter
  4712.     loop    egadmp2            ; next group across scan line
  4713.     pop    cx            ; recover scan line counter
  4714.     loop    egadmp1            ; do next scan line
  4715.     call    egadmpw            ; flush the buffer for last scan line
  4716. egadmp9:mov    ah,close2        ; close the file
  4717.     mov    bx,dhandle
  4718.     int    dos
  4719.     mov    dhandle,-1        ; set handle to unused
  4720.     xor    di,di
  4721.     call    psetup
  4722.     pop    es
  4723.     ret
  4724.                        ; local worker
  4725. egadmpw:push    bx            ; write tempbuf from start to [bx-1]
  4726.     push    cx
  4727.     mov    dx,offset tempname    ; work buffer
  4728.     mov    cx,bx            ; buffer pointer to next free byte
  4729.     sub    cx,dx            ; buffer size to write
  4730.     cmp    cx,0
  4731.     jle    egadmpw1        ; le = nothing to write
  4732.     mov    bx,dhandle        ; file handle
  4733.     mov    ah,write2        ; write cx bytes from tempname
  4734.     int    dos
  4735.     jc    egadmpw2        ; c = error
  4736.     cmp    ax,cx            ; wrote all?
  4737.     jne    egadmpw2        ; ne = no
  4738. egadmpw1:clc                ; clc
  4739.     pop    cx
  4740.     pop    bx
  4741.     ret
  4742. egadmpw2:stc                ; carry set for failure
  4743.     pop    cx
  4744.     pop    bx
  4745.     ret
  4746.  
  4747. egadmp    endp
  4748.  
  4749. ; Worker. Write Kermit version and current date and time in TIFF header
  4750. dmpdate    proc    near
  4751.     mov    di,offset prog+10    ; place for version in prog field
  4752.     mov    ax,version        ; Kermit version
  4753.     call    dec2di            ; write the version
  4754.     mov    ah,getdate        ; DOS date (cx= yyyy, dh= mm, dl= dd)
  4755.     int    dos
  4756.     mov    di,offset dandt        ; where to write
  4757.     mov    ax,cx            ; get yyyy
  4758.     push    dx
  4759.     call    dec2di            ; write to buffer
  4760.     pop    dx
  4761.     mov    byte ptr [di],':'
  4762.     inc    di
  4763.     mov    al,dh            ; mm
  4764.     cmp    al,10            ; leading digit?
  4765.     jae    dmpdat1            ; ae = yes
  4766.     mov    byte ptr [di],'0'    ; make our own
  4767.     inc    di
  4768. dmpdat1:xor    ah,ah
  4769.     push    dx
  4770.     call    dec2di
  4771.     mov    byte ptr [di],':'
  4772.     pop    dx
  4773.     inc    di
  4774.     mov    al,dl            ; dd
  4775.     cmp    al,10            ; leading digit?
  4776.     jae    dmpdat2            ; ae = yes
  4777.     mov    byte ptr [di],'0'    ; make our own
  4778.     inc    di
  4779. dmpdat2:xor    ah,ah
  4780.     call    dec2di
  4781.     mov    byte ptr [di],' '
  4782.     inc    di
  4783.     mov    ah,gettim        ; DOS tod (ch=hh, cl=mm, dh=ss, dl=.s)
  4784.     int    dos
  4785.     push    dx            ; save dx
  4786.     xor    ah,ah
  4787.     mov    al,ch            ; Hours
  4788.     cmp    al,10            ; leading digit?
  4789.     jae    dmpdat3            ; ae = yes
  4790.     mov    byte ptr [di],'0'    ; make our own
  4791.     inc    di
  4792. dmpdat3:push    cx
  4793.     call    dec2di            ; write decimal asciiz to buffer
  4794.     pop    cx
  4795.     mov    byte ptr [di],':'
  4796.     inc    di
  4797.     xor    ah,ah
  4798.     mov    al,cl            ; Minutes
  4799.     cmp    al,10            ; leading digit?
  4800.     jae    dmpdat4            ; ae = yes
  4801.     mov    byte ptr [di],'0'    ; make our own
  4802.     inc    di
  4803. dmpdat4:call    dec2di            ; write decimal asciiz to buffer
  4804.     mov    byte ptr [di],':'
  4805.     inc    di
  4806.     pop    dx
  4807.     xor    ah,ah
  4808.     mov    al,dh            ; Seconds
  4809.     cmp    al,10            ; leading digit?
  4810.     jae    dmpdat5            ; ae = yes
  4811.     mov    byte ptr [di],'0'    ; make our own
  4812.     inc    di
  4813. dmpdat5:call    dec2di            ; write decimal asciiz to buffer
  4814.     inc    di
  4815.     ret
  4816. dmpdate    endp
  4817.  
  4818. ; Dispatch table processor. Enter with BX pointing at table of {char count,
  4819. ; address of action routines, characters}. Jump to matching routine or return.
  4820. ; Enter with AL holding received Final char.
  4821. atdispat proc near
  4822.     mov    cl,[bx]            ; get table length from first byte
  4823.     xor    ch,ch
  4824.     mov    di,bx            ; main table
  4825.     add    di,3            ; point di at first char in table
  4826.     push    es
  4827.     push    ds
  4828.     pop    es            ; use data segment for es:di below
  4829.     cld                ; set direction forward
  4830.     repne    scasb            ; find matching character
  4831.     pop    es
  4832.     je    atdisp2            ; e = found a match, get action addr
  4833.     cmp    al,' '            ; control char?
  4834.     jb    atdisp1            ; b = yes
  4835.     ret                ; ignore escape sequence
  4836. atdisp1:jmp    tekctl            ; process control char
  4837. atdisp2:sub    di,bx            ; distance scanned in table
  4838.     sub    di,4            ; skip count byte, address word, inc
  4839.     shl    di,1            ; convert to word index
  4840.     inc    bx            ; point to address of action routines
  4841.     mov    bx,[bx]            ; get address of action table
  4842.     jmp    word ptr [bx+di]    ; dispatch to the routine
  4843. atdispat endp
  4844.  
  4845. ansich    proc    near            ; insert Pn spaces at and after cursor
  4846.     mov    cx,param        ; get Pn
  4847.     or    cx,cx
  4848.     jnz    ansich1            ; got a value
  4849.     inc    cx            ; zero means one
  4850. ansich1:push    x_coord
  4851.     push    y_coord
  4852.     mov    al,spcontrol        ; preserve space control
  4853.     mov    tempname,al        ; save here
  4854.     mov    spcontrol,1        ; turn on destructive space
  4855.     and    x_coord,not 7        ; modulo 8x8 cells
  4856.     mov    ax,xmax            ; start of last cell
  4857.     sub    ax,x_coord        ; start of current cell
  4858.     shr    ax,1            ; divide by 8 dots per char
  4859.     shr    ax,1
  4860.     shr    ax,1
  4861.     cmp    ax,cx            ; want more spaces than are on line?
  4862.     jae    ansich2            ; ae = no
  4863.     mov    cx,ax            ; clip to right margin
  4864.     jcxz    ansich3            ; z = nothing to do
  4865. ansich2:push    cx
  4866.     mov    al,' '            ; a space
  4867.     call    outscrn            ; write to screen
  4868.     pop    cx
  4869.     loop    ansich2            ; do them
  4870. ansich3:mov    al,tempname        ; space control
  4871.     mov    spcontrol,al        ; restored
  4872.     pop    x_coord
  4873.     pop    y_coord
  4874.     call    remcursor        ; remove text cursor symbol
  4875.     call    setcursor        ; draw cursor at new location
  4876.     ret
  4877. ansich    endp
  4878.                     ; scaled by text screen height
  4879. atcuu    proc    near            ; cursor up Pn lines
  4880.     cmp    param,0            ; empty arg?
  4881.     jne    atcuu1            ; got a value
  4882.     inc    param            ; zero means one
  4883. atcuu1:    mov    ax,y_coord        ; where we are now
  4884.     add    ax,4            ; round up a smidge
  4885.     mov    cl,byte ptr low_rgt+1    ; highest text line
  4886.     xor    ch,ch
  4887.     mul    cx            ; proportion
  4888.     xor    dx,dx
  4889.     mov    cx,ybot            ; highest scan line
  4890.     div    cx            ; end, estimate currren text line
  4891.     sub    ax,param
  4892.     inc    ax            ; count lines from 1 again
  4893.     mov    param,ax        ; new text row
  4894.     jmp    atcva            ; do as absolute
  4895. atcuu    endp
  4896.  
  4897.                     ; scaled by text screen height
  4898. atcud    proc    near            ; cursor down Pn lines
  4899.     cmp    param,0            ; get Pn
  4900.     jne    atcud1            ; ne = got a value
  4901.     inc    param            ; zero means one
  4902. atcud1:    mov    ax,y_coord        ; where we are now
  4903.     add    ax,4            ; round up a smidge
  4904.     mov    cl,byte ptr low_rgt+1    ; highest text line
  4905.     xor    ch,ch
  4906.     mul    cx            ; proportion
  4907.     xor    dx,dx
  4908.     mov    cx,ybot            ; highest scan line
  4909.     div    cx            ; end, estimate currren text line
  4910.     inc    ax            ; count lines from 1 again
  4911.     add    param,ax        ; new text row
  4912.     jmp    atcva            ; do as absolute
  4913. atcud    endp
  4914.  
  4915. atcuf    proc    near            ; cursor forward Pn columns
  4916.     mov    ax,param        ; get Pn
  4917.     or    ax,ax
  4918.     jnz    atcuf1            ; got a value
  4919.     inc    ax            ; zero means one
  4920. atcuf1:    shl    ax,1            ; times 8 dots per char cell
  4921.     shl    ax,1
  4922.     shl    ax,1            ; Tek columns worth
  4923.     and    x_coord,not 7        ; modulo 8x8 cells
  4924.     add    x_coord,ax        ; forward to absolute column
  4925.     mov    ax,xmax
  4926.     cmp    x_coord,ax        ; beyond right most cell?
  4927.     jbe    atcuf2            ; be = no
  4928.     mov    x_coord,ax        ; limit to right
  4929. atcuf2:    call    remcursor        ; remove text cursor symbol
  4930.     call    setcursor        ; draw cursor at new location
  4931.     ret
  4932. atcuf    endp
  4933.  
  4934. atcub    proc    near            ; cursor left/back Pn columns
  4935.     mov    ax,param        ; get Pn
  4936.     or    ax,ax
  4937.     jnz    atcub1            ; got a value
  4938.     inc    ax            ; zero means one
  4939. atcub1:    shl    ax,1
  4940.     shl    ax,1
  4941.     shl    ax,1            ; times 8 dots per cell
  4942.     and    x_coord,not 7        ; modulo 8x8 cells
  4943.     mov    cx,xmax
  4944.     cmp    x_coord,cx        ; beyond last col (wrap pending)?
  4945.     jbe    atcub3            ; be = no
  4946.     mov    x_coord,cx        ; set to last col
  4947. atcub3:    sub    x_coord,ax        ; back up
  4948.     jnc    atcub2            ; nc = ok
  4949.     mov    x_coord,0        ; stop in column zero
  4950. atcub2:    call    remcursor        ; remove text cursor symbol
  4951.     call    setcursor        ; draw cursor at new location
  4952.     ret
  4953. atcub    endp
  4954.  
  4955. atcnl    proc    near            ; do Pn cr/lf's
  4956.     mov    x_coord,0        ; to left margin
  4957.     jmp    atcud            ; do the cursor downs
  4958. atcnl    endp
  4959.  
  4960. atcpl    proc    near            ; do Pn cursor ups
  4961.     jmp    atcuu            ; do the cursor ups
  4962. atcpl    endp
  4963.  
  4964.                     ; scaled by text screen width
  4965. atcha    proc    near            ; cursor to absolute column
  4966.     and    x_coord,not 7        ; modulo 8x8 cells
  4967.     mov    ax,param        ; get Pn
  4968.     or    ax,ax
  4969.     jz    atcha1            ; z = zero already
  4970.     dec    param            ; count columns from 0
  4971.     mov    ax,xmax            ; number of Tek dots/row
  4972.     mul    param            ; times columns they want
  4973.     mov    cl,byte ptr low_rgt    ; number of last text column
  4974.     xor    ch,ch
  4975.     xor    dx,dx
  4976.     div    cx            ; scale to ~80 column screen
  4977.     cmp    ax,xmax            ; too far?
  4978.     jbe    atcha1            ; be = no
  4979.     mov    ax,xmax            ; right most column
  4980. atcha1:    mov    x_coord,ax
  4981.     call    remcursor        ; remove text cursor symbol
  4982.     call    setcursor        ; draw cursor at new location
  4983.     ret
  4984. atcha    endp
  4985.                     ; scaled by text screen height
  4986. atcva    proc    near            ; cursor to absolute row
  4987.     dec    param            ; count from 0
  4988.     mov    ax,param        ; desired text row
  4989.     or    ax,ax            ; zero or now -1?
  4990.     jg    atcva1            ; g = no, further down
  4991.     mov    ax,7            ; bottom of top text cell
  4992.     jmp    short atcva2
  4993. atcva1:    mov    ax,ybot
  4994.     inc    ax            ; number of scan lines on screen
  4995. ;;;;    and    ax,not 7        ; whole 8x8 char cells
  4996.     mul    param            ; times row they want
  4997.     mov    cl,byte ptr low_rgt+1    ; number of last text line (0..23)
  4998.     xor    ch,ch
  4999.     xor    dx,dx
  5000.     div    cx            ; scale to ~24 line screen 
  5001.     mov    cx,ybot
  5002. ;;;;    and    cx,not 7        ; whole 8x8 char cells
  5003.     cmp    ax,cx            ; too far?
  5004.     jbe    atcva2            ; be = no
  5005.     mov    ax,cx
  5006. atcva2:    mov    y_coord,ax        ; go to that line
  5007.     call    remcursor        ; remove text cursor symbol
  5008.     call    setcursor        ; draw cursor at new location
  5009.     ret
  5010. atcva    endp
  5011.     
  5012. atcup    proc    near            ; cursor to absolute row, column
  5013.     call    atcva            ; process param[0] as absolute row
  5014.     push    param[2]        ; column
  5015.     pop    param
  5016.     jmp    atcha            ; process param[2] as absolute column
  5017. atcup    endp
  5018.  
  5019. ated    proc    near            ; erase display
  5020.     mov    al,spcontrol        ; preserve space control
  5021.     mov    tempname,al        ; save here
  5022.     mov    spcontrol,1        ; turn on destructive space
  5023.     push    x_coord
  5024.     push    y_coord            ; save cursor
  5025.     cmp    param,0            ; cursor to end of screen?
  5026.     je    ated1            ; e = yes
  5027.     cmp    param,1            ; start of screen to cursor?
  5028.     je    ated3            ; e = yes
  5029.     cmp    param,2            ; entire screen?
  5030.     je    ated5            ; e = yes
  5031.     ret                ; else ignore
  5032.  
  5033. ated1:    mov    param,0            ; cursor to end of this line
  5034.     call    atel            ; erase cursor to end of line
  5035.     add    y_coord,8        ; look at next line
  5036.     mov    ax,ybot
  5037.     cmp    y_coord,ax        ; are we at the end now?
  5038.     ja    ated6            ; a = yes
  5039.     mov    x_coord,0        ; start of line is here
  5040.     jmp    ated1            ; do through last line
  5041.  
  5042. ated3:    and    y_coord,not 7        ; modulo 8x8 char cells
  5043.     mov    cx,y_coord        ; start of screen to cursor
  5044.     shr    cx,1            ; char lines at 8 dots/char
  5045.     shr    cx,1
  5046.     shr    cx,1
  5047.     dec    cx            ; omit current line= # whole lines
  5048.     or    cx,cx            ; any whole lines?
  5049.     jle    ated3b            ; le = no
  5050.     mov    y_coord,7        ; start at the top line
  5051. ated3a:    push    cx
  5052.     mov    param,2            ; entire line
  5053.     call    atel            ; erase entire line
  5054.     add    y_coord,8        ; next line
  5055.     pop    cx
  5056.     loop    ated3a
  5057. ated3b:    mov    param,1            ; start of line to cursor
  5058.     call    atel            ; erase to cursor on this (last) line
  5059.     jmp    short ated6
  5060.  
  5061. ated5:    call    tekcls            ; erase whole screen
  5062.  
  5063. ated6:    mov    al,tempname        ; spacing control
  5064.     mov    spcontrol,al
  5065.     pop    y_coord
  5066.     pop    x_coord
  5067.     call    remcursor        ; remove last cursor
  5068.     call    setcursor        ; set cursor to original position
  5069.     ret
  5070. ated    endp
  5071.  
  5072. atech    proc    near            ; erase Pn chars from cursor to eol
  5073.     mov    al,spcontrol        ; preserve space control
  5074.     mov    tempname,al        ; save here
  5075.     mov    spcontrol,1        ; turn on destructive space
  5076.     push    x_coord
  5077.     push    y_coord            ; save cursor
  5078.     mov    cx,x_coord
  5079.     and    cx,not 7        ; modulo 8x8 cells
  5080.     mov    ax,xmax
  5081.     sub    ax,cx            ; number of chars remaining on line
  5082.     shr    ax,1
  5083.     shr    ax,1
  5084.     shr    ax,1
  5085.     inc    ax            ; count cursor cell
  5086.     mov    cx,param        ; how many chars to erase
  5087.     or    cx,cx
  5088.     jz    atech1            ; z = zero, use one
  5089.     inc    cx
  5090. atech1:    cmp    ax,cx            ; want more than line length?
  5091.     jae    atech2            ; ae = no
  5092.     mov    cx,ax            ; clip at right margin
  5093.     or    cx,cx
  5094.     jle    atech3            ; le = nothing to do
  5095. atech2:    push    cx
  5096.     mov    al,' '
  5097.     call    outscrn            ; write spaces
  5098.     pop    cx
  5099.     loop    atech2
  5100. atech3:    mov    al,tempname        ; spacing control
  5101.     mov    spcontrol,al
  5102.     pop    y_coord
  5103.     pop    x_coord
  5104.     call    remcursor        ; remove last cursor
  5105.     call    setcursor        ; set cursor to original position
  5106.     ret
  5107. atech    endp
  5108.  
  5109. atel    proc    near            ; erase on this line
  5110.     call    remcursor        ; remove cursor
  5111.     push    x_coord
  5112.     push    y_coord
  5113.     cmp    param,0            ; cursor to end of line?
  5114.     je    atel1            ; e = yes
  5115.     cmp    param,1            ; start of line to cursor?
  5116.     je    atel3            ; e = yes
  5117.     cmp    param,2            ; whole line?
  5118.     jne    atel5            ; ne = no, fail
  5119.     mov    x_coord,0        ; erase entire line
  5120.  
  5121. atel1:    mov    cx,xmax            ; cursor to end of line
  5122.     mov    ax,x_coord
  5123.     and    ax,not 7        ; modulo 8x8 cells
  5124.     sub    cx,ax
  5125.     shr    cx,1
  5126.     shr    cx,1
  5127.     shr    cx,1            ; 8 dots/char
  5128.     inc    cx            ; count the cursor cell
  5129.     or    cx,cx
  5130.     jle    atel5            ; le = do nothing
  5131.     mov    al,spcontrol        ; preserve space control
  5132.     mov    tempname,al        ; save here
  5133.     mov    spcontrol,1        ; turn on destructive space
  5134. atel2:    push    cx            ; start of line to cursor
  5135.     mov    al,' '
  5136.     call    outscrn
  5137.     pop    cx
  5138.     loop    atel2
  5139.     mov    al,tempname        ; space control
  5140.     mov    spcontrol,al        ; restored
  5141. atel5:    pop    y_coord
  5142.     pop    x_coord
  5143.     call    remcursor        ; remove last cursor
  5144.     call    setcursor        ; set cursor to original position
  5145.     ret
  5146. atel3:    mov    cx,x_coord        ; start of line to cursor
  5147.     shr    cx,1
  5148.     shr    cx,1
  5149.     shr    cx,1
  5150.     inc    cx            ; count cursor cell
  5151.     mov    x_coord,0        ; go to start of line
  5152.     jmp    atel2            ; do the loops
  5153. atel    endp
  5154. code2    ends
  5155.     end
  5156.